近期项目中对xml的解析比较多,我们采用的是dom4j这个工具来进行xml解析的,下面将自己在项目中用到的一些方法记录下来。
一.Document对象的几种获取方法
1.使用SAXReader
① 读xml文件
SAXReader reader = new SAXReader();
Document document = reader.read(File);
②读xml字符串
SAXReader reader = new SAXReader();
Document document = reader.read(xmlString.getBytes());
2.使用DocumentHelper
Document document = DocumentHelper.parseText(xmlString);
二.获取xml元素
1.获取根节点
Element root = document.getRootElement();
2.获取指定元素名称的节点
//元素名称唯一
Element element = root.element("elementName");
//多个元素有相同的名称
List<Element> list = root.elements("elementName");
3.迭代节点
Element element = root.element("elementName");
Iterator iter = element.elementIterator();
while(iter.hasNext()){
Element tmp = iter.next();
if(tmp.getName().equals("elementName")){
//获取节点的内容
String text = tmp.getText();
//修改节点的值为“hahaha”
tmp.setText("hahaha");
}
}
三.XPath的使用
XPath的使用首先要引入XPath的jar文件。使用XPath能方便查找元素,XPath采用类型文件路径的方式来对元素进行查找,例如:
List<Element> elements = document.selectNodes("/root/package/envelopInfo");//获取root节点下的package节点下的所有envelopInfo节点
//当然使用“//”可以用来表示更节点如:
List<Element> elements = document.selectNodes("//package/envelopInfo");//效果和上面的一样
但是在有的场景下,xml文件是带有命名空间的,比如signature.xml:
<?xml version="1.0" encoding="GBK"?>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="ID000000">
<SignedInfo Id="ID000001">
<SignatureValue Id="ID000004">tFgL7wn2WGrwmgzxJPM7Lxaxc1ayN2Ltzz7iDvK7I=</SignatureValue>
<KeyInfo Id="ID000005">
<KeyValue>
<X509Data>
</X509Data>
</KeyValue>
</KeyInfo>
<Object Encodeing="GBK" Id="object" MimeType="String">
<package>12345567888</package>
</Object>
</Signature>
我们可以看到signature.xml含有命名空间xmlns=http://www.w3.org/2000/09/xmldsig#,这时候又有dom4j无法读取带命名空间的节点,所以在解析的时候先设置XPath的命名空间,然后在每个节点前都要加上命名空间来取。例子如下:
//①xml是文件
Map<String,String> nameSpace = new HashMap<String,String>();
nameSpace.put("xmln","http://www.w3.org/2000/09/xmldsig#");
SAXReader reader = new SAXReader();
reader.getDocumentFactory().setXPathNamespaceURIs(nameSpace);
Document dom = reader.read(signature.xml);
List listSingedInfo = dom.selectNodes("//xmln:SignedInfo");//获取SignedInfo节点
List listSignatureValue = dom.selectNodes("//xmln:SignedInfo/xmln:SignatureValue")//获取SignatureValue节点
//②xml是字符串
Map<String,String> nameSpace = new HashMap<String,String>();
nameSpace.put("xmln","http://www.w3.org/2000/09/xmldsig#");
Document dom = DocumentHelper.parseText(signature);
XPath xpath = dom.createXPath("//xmln:SignedInfo");//获取SignedInfo节点
xpath.setNamespaceURIs(nameSpace);
List list = xpath.selectNodes(dom);
xpath = dom.createXPath("//xmln:SignedInfo/xmln:SignatureValue");//获取SignatureValue节点
xpath.setNamespaceURIs(nameSpace);
List list = xpath.selectNodes(dom);
四.XML的CDATA
如果在一个节点里存放了带有"<","&"字符的字符串,在浏览xml的时候会发现这些字符被转义了,这显然不是我们想要的。
CDATA的作用就是,保护这些字符不被自动转义,格式是<![CDATA[ .......]]。这个格式不能用硬编码的方式写到Dom对象里,
不过Dom4j已经提供了对CDATA的操作,示例:
场景:假设要在signature.xml的<package>里面插入下面一段字符串xmlString:
<?xml version="1.0" encoding="GBK"?>
<message>
<id>1</id>
<version>2005</version>
</message>
方法:
Map<String,String> nameSpace = new HashMap<String,String>();
nameSpace.put("xmln","http://www.w3.org/2000/09/xmldsig#");
Document dom = DocumentHelper.parseText(signature);
XPath xpath = dom.createXPath("//xmln:Object/xmln:package");//获取package节点
xpath.setNamespaceURIs(nameSpace);
List list = xpath.selectNodes(dom);
Element package = list.get(0);
CDATA cdata = DocumentHelper.createCDATA(xmlString);//添加CDATA的内容
package.add(cdata);// 添加CDATA到package标签里面