项目需求对存在数据库里的xml进行解析,转为java中。试了很多种方法,最后还是采取遍历根节点和子节点的方式获取。(适用于xml中层层嵌套的情况),这里吐槽下,这种需求真的是云需求。
1.xml样式
<?xml version="1.0" encoding="GBK"?>
<conditions>
<condition queryType="2888196">
<item>
<name>subreportIDs</name>
<value>96027</value>
<item>
<name>name</name>
<value>郭子仪</value>
</item>
</condition>
</conditions>
2.pom.xml
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.8.11</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.11</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.8.11</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.8.11</version>
</dependency>
<!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.2.0</version>
</dependency>
3.实体类
import java.util.List;import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;public class condition {
List<item> item; //item列表
@JacksonXmlProperty(isAttribute = true, localName = "queryType")
private String queryType; //属性
public String getQueryType() {
return queryType;
}public void setQueryType(String queryType) {
this.queryType = queryType;
}
@JacksonXmlProperty(localName = "item")
@JacksonXmlElementWrapper(useWrapping = false)
public List<item> getItem() {
return item;
}public void setItem(List<item> item) {
this.item = item;
}
}
@JacksonXmlRootElement(localName = "conditions")
public class Group {
condition condition; //conditionpublic condition getCondition() {
return condition;
}
public void setCondition(condition condition) {
this.condition = condition;
}
}
public class item {
private String name;
private String value;
public String getName() {
return name;
}public void setName(String name) {
this.name = name;
}public String getValue() {
return value;
}public void setValue(String value) {
this.value = value;
}
}
4.工具类dom4j用来xml转换list
/**
* TODO 解析xml.
*
* @author xhnronin
* @version $Revision:$
*/
public class XmlAnalysisUtil {
/**
* 解析指定xml节点下的信息
*
* @param xmlStr xml格式的字符串
* @param xmlPath xml里元素路径
* @return 返回List,如map.get("delay")就可取到下面的5000 <timer> <delay>5000</delay> <period>60000</period> </timer>
* @throws DocumentException
*/
public static List<Map<String,String>> parserXml(String xmlStr, String xmlPath) throws DocumentException {
Document document;
document = DocumentHelper.parseText(xmlStr);
Element root=document.getRootElement();
System.out.println("根节点名称"+root.getName());
List<Map<String,String>> rList = new ArrayList<Map<String,String>>();
//遍历下面的节点,获取
List<Document> list = document.selectNodes(xmlPath);
for (int i = 0; i < list.size(); i++) {
Map<String, String> map = new HashMap<String, String>();
Element timer = (Element) list.get(i);
for (Iterator<Document> j = timer.elementIterator(); j.hasNext();) {
Element node = (Element) j.next();
System.out.println(node.getName() + ":" + node.getText());
map.put(node.getName(), node.getText());
}
rList.add(map);
}
return rList;
}
}
5.测试类,主方法
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args ) throws IOException, DocumentException
{
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.setDefaultUseWrapper(false);
//字段为null,自动忽略,不再序列化
xmlMapper.setSerializationInclusion(Include.NON_NULL);
//XML标签名:使用骆驼命名的属性名,
xmlMapper.setPropertyNamingStrategy(PropertyNamingStrategy.UPPER_CAMEL_CASE);
//设置转换模式
xmlMapper.enable(MapperFeature.USE_STD_BEAN_NAMING);//序列化 bean--->xml
Group group = new Group();
condition conditions=new condition();
item item1=new item();
item1.setName("subreportIDs");
item1.setValue("96027");
item item2=new item();
item2.setName("name");
item2.setValue("过子文");
List<item>items=new ArrayList<item>();
items.add(item1);
items.add(item2);
conditions.setItem(items);
conditions.setQueryType("25196");
group.setCondition(conditions);//美化sql会产出换行符号,解析会错误
// xmlMapper.enable(SerializationFeature.INDENT_OUTPUT);
String result = xmlMapper.writeValueAsString(group);
System.out.println("序列化结果:" + result);
XmlAnalysisUtil util=new XmlAnalysisUtil();
List<Map<String,String>>hash =util.parserXml(result, "/conditions/Condition/item");
System.out.println(hash);
}
}
6.结果
序列化结果:
<conditions>
<Condition queryType="25196">
<item><Name>subreportIDs</Name>
<Value>96027</Value>
</item>
<item>
<Name>name</Name>
<Value>过子文</Value>
</item>
</Condition>
</conditions>
根节点名称conditions
Name:subreportIDs
Value:96027
Name:name
Value:郭子仪
[{Value=96027, Name=subreportIDs}, {Value=过子文, Name=name}]。
7.注意
此处应该能使用Jackson反序列换,然而,可能是层层嵌套的关系(博主这种对象里还有对象的)会出现生成成功,解析却会失败的情况。(求大佬解决)
因此只能使用dom4j取出来,如果是这种层层嵌套,还是写遍历节点的方式不容易束手无策。(老古董麻烦却还是好改)
工具类里,因为是取xml里的name,和value为一对属性,因此使用 List<Map<String,String>>,各位可以根据相应的需求修改,
timer.elementIterator();
这个是遍历此节点下的子节点。比如我的xml中传到的xpath是"/conditions/Condition/item",相应的遍历的是<item>下的子节点。
而如果子节点下面还有则需要修改。