dom4j解析xml原理详解

dom4j组件配合xPath解析xml,两个重点:dom4j对xml的操作;xPath对xml节点的匹配。


一、dom4j操作xml:

常用到的对象:

SAXReader:读取xml文件到Document树结构文件对象。

Document:是一个xml文档对象树,类比Html文档对象。具有跟节点、元素节点、父节点、子节点;属性节点、文本节点、注释节点;有id、class等这些属性。

Element:元素节点。通过Document对象可以查找单个元素,可以对元素节点进行常见的ACID操作。其中查询是最基本的应用,使用对象的方法,配合xPath的路径匹配解析模式。


常用的方法:


获取dom树的方法:

SAXReader reader = new SAXReader();

InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("sys-config.xml");

Document doc = reader.read(in);

读取跟节点的方法:

doc.getRootElement();

获取某个节点的方法:

Element driverNameElt = (Element)doc.selectObject("/config/db-info/driver-name");

Element beanElt=(Element)doc.selectSingleNode("//bean[@id=\""+c.getName()+"\"]");

获取某类节点集合的方法:

List daoFactorylist = doc.selectNodes("/config/dao-factory/*");


常见的使用:读取xml、获取跟节点、遍历节点。

1、读取文档:

[java]  view plain  copy
  1. <span style="font-size:18px;">   private File inputXml;  
  2.      public Document getDocument() {  
  3.             SAXReader saxReader = new SAXReader();  
  4.             Document document = null;  
  5.             try {  
  6.                 document = saxReader.read(inputXml);  
  7.             } catch (DocumentException e) {  
  8.                 e.printStackTrace();  
  9.             }  
  10.             return document;  
  11.          }</span>  

2、获取跟节点:

[java]  view plain  copy
  1. <span style="font-size:18px;">    public Element getRootElement() {  
  2.        return getDocument().getRootElement();  
  3.     }</span>  

3、枚举根节点下的所有节点:

[java]  view plain  copy
  1. <span style="font-size:18px;">  Element root = getRootElement();  
  2.       
  3.     for (Iterator ie = root.elementIterator(); ie.hasNext();) {  
  4.             System.out.println("======");  
  5.             Element element = (Element) ie.next();  
  6.             System.out.println(element.getName());  
  7.     }  
  8. </span>  

4、枚举所有属性节点:

[java]  view plain  copy
  1. <span style="font-size:18px;"for (Iterator ia = element.attributeIterator(); ia.hasNext();) {  
  2.               Attribute attribute = (Attribute) ia.next();  
  3.               System.out.println(attribute.getName() + ":"  
  4.                      + attribute.getData());  
  5.     }</span>  

5、枚举当前节点下的所有子节点:
[java]  view plain  copy
  1. <span style="font-size:18px;"for (Iterator ieson = element.elementIterator(); ieson.hasNext();) {  
  2.               Element elementSon = (Element) ieson.next();  
  3.               System.out.println(elementSon.getName() + ":"  
  4.                      + elementSon.getText());  
  5.  }</span>  

6、获取并遍历某个节点下的所有子节点: 
[java]  view plain  copy
  1. <span style="font-size:18px;">                      List daoFactorylist = doc.selectNodes("/config/dao-factory/*");  
  2.               
  3.               
  4.             for (int i=0; i<daoFactorylist.size(); i++) {  
  5.                 Element daoFactoryElt = (Element)daoFactorylist.get(i);  
  6.                 String tagName = daoFactoryElt.getName();  
  7.                 String tagText = daoFactoryElt.getText();  
  8.                 System.out.println("读取DaoFactory-->>" + tagText);  
  9.                   
  10.                 //放入到Map中  
  11.                 daoFactoryMap.put(tagName, tagText);  
  12.                   
  13.                   
  14.             }  
  15. </span>  


二、xPath对路径的解析:

1、基本语法:

*

 

现节点下所有元素

 

*/Elem

 

现节点下所有节点的字节点中为“Elem”的节点

 

@Prop

 

属性值

 

@*

 

所有属于现节点的属性

 

.

 

现节点

 

..

 

现节点的上级

 

Elem[i]

 

现节点下第i个叫做Elem的元素(从1开始)

 

Elem[position() = 1]

 

现节点下第1个叫做Elem的元素(从1开始)

 

Elem/[@prop=“somevalue”]

 

现节点下,名字为Elem,具有prop的属性,并且属性值为somevalue的,那个元素

 

Elem1|elem2

 

现节点下,名字为Elem1或elem2的元素

 

.//elem

 

现节点下,可以跨越级别,所有的名字叫做elem的元素

 

Elem1//elem2

 

现节点下,可以跨越级别,所有的名字叫做elem2,且elem2的上级中有人叫Elem1,且Elem1是现节点的子元素,的元素

 


2、xPath节点类型:
  包括:根节点、元素节点、文本节点、属性节点、命名空间节点、处理指令节点、注释节点。与即是xml的节点类型相同。
3、以下面的xml树为例说明几种解析匹配模式:
 

[html]  view plain  copy
  1. <A id="a1">  
  2.   <B id="b1">  
  3.         <C id="c1">  
  4.           <B name="b"/>  
  5.           <D id="d1"/>  
  6.           <E id="e1"/>  
  7.           <E id="e2"/>  
  8.         </C>  
  9.   </B>  
  10.   <B id="b2"/>  
  11.   <C id="c2">  
  12.         <B/>  
  13.         <D id="d2"/>  
  14.         <F/>  
  15.   </C>  
  16.   <E/>  
  17. </A>  

1.按照路径解析:与文件路径的匹配相仿

(1)用“/”指示节点路径

如“/A/C/D” 表示节点"A"的子节点"C"的子节点"D",即id值为d2的D节点, “/”表示根节点。

(2)用“//”表示所有路径以"//"后指定的子路径结尾的元素

如“//E” 表示所有E元素,结果是所有三个E元素, 如“//C/E”表示所有父节点为C的E元素,结果是id值为e1和e2的两个E元素 。

(3)用“*”表示路径的通配符

如“/A/B/C/*”表示 A元素→B元素→C元素下的所有子元素,即name值为b的B元素、 id值为d1的D元素和id值为e1和e2的两个E元素

“/*/*/D”

“/*/*/D”表示上面有两级节点的D元素,匹配结果是id值为d2的D元素 , 如“//*”表示所有的元素。 

2.按照属性解析:使用@前缀表明是用属性匹配

//B[@id]表示所有具有属性id的B元素,结果为id值为b1和b2的两个B元素

//B[@*]表示所有具有属性的B元素,结果为两个具有id属性的B元素和一个具有name属性B元素

//B[not(@*)]表示所有不具有属性的B元素,结果为A元素→C元素下的B元素

//B[@id="b1"] id值为b1的B元素,结果为A元素下的B元素

3.按照位置解析:

/A/B/C[1]表示A元素→B元素→C元素的第一个子元素,得到name值为b的B元素

/A/B/C[last()]表示A元素→B元素→C元素的最后一个子元素,得到id值为e2的E元素

/A/B/C[position()>1]表示A元素→B元素→C元素之下的位置号大于1的元素,得到id值为d1的D元素和两个具有id值的E元素



4.按照亲属关系解析:常见的关系有父亲、孩子、祖先(父节点及父节点以上)、后代、兄弟。

//E/parent::* 表示所有E节点的父节点元素,结果为id值为a1的A元素和id值为c1的C元素

//F/ancestor::* 表示所有F元素的祖先节点元素,结果为id值为a1的A元素和id值为c2的C元素

/A/child::* 表示A的子元素,结果为id值为b1、b2的B元素,id值为c2的C元素,以及没有任何属性的E元素

/A/descendant::* 表示A的所有后代元素,结果为除A元素以外的所有其它元素

//F/self::* 表示所有F的自身元素,结果为F元素本身

//F/ancestor-or-self::* 表示所有F元素及它的祖先节点元素,结果为F元素、F元素的父节点C元素和A元素

/A/C/descendant-or-self::* 表示所有A元素→C元素及它们的后代元素,结果为id值为c2的C元素、该元素的子元素B、D、F元素

/A/C/following-sibling::* 表示A元素→C元素的紧邻的后序所有兄弟节点元素,结果为没有任何属性的E元素

/A/C/preceding-sibling::* 表示A元素→C元素的紧邻的前面所有兄弟节点元素,结果为id值为b1和b2的两个B元素

/A/B/C/following::* 表示A元素→B元素→C元素的后序的所有元素,结果为id 为b2的B元素、无属性的C元素、无属性的B元素、id为d2的D



元素、无属性的F元素、\无属性的E元素。

/A/C/preceding::*表示A元素→C元素的前面的所有元素,结果为id为b2的B元素、id为e2的E元素、id为e1的E元素、id为d1的D元素、name



为 b的B元素、id为c1的C元素、id为b1的B元素 



5.函数解析:

last()、position()等,不为重点。



三、实例应用:
1、将Oracle数据库配置信息写到xml文件中,使用dom4j解析:
sys-config.xml文件:

[html]  view plain  copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <config>  
  3.     <db-info>  
  4.         <driver-name>oracle.jdbc.driver.OracleDriver</driver-name>  
  5.         <url>jdbc:oracle:thin:@localhost:1521:orcl</url>  
  6.         <user-name>drp1</user-name>  
  7.         <password>drp1</password>  
  8.     </db-info>  
  9.   
  10.   
  11. </config>  


XmlConfigReader类的构造函数:
[java]  view plain  copy
  1. private XmlConfigReader() {  
  2.       
  3.       
  4.     SAXReader reader = new SAXReader();  
  5.       
  6.     InputStream in = <strong>Thread.currentThread().getContextClassLoader().getResourceAsStream</strong>("sys-config.xml");  
  7.     try {  
  8.                          
  9.           
  10.           
  11.         Document doc = reader.read(in);  
  12.           
  13.         //取得jdbc相关配置信息  
  14.         Element driverNameElt = (Element)doc.selectObject("/config/db-info/driver-name");  
  15.         Element urlElt = (Element)doc.selectObject("/config/db-info/url");  
  16.         Element userNameElt = (Element)doc.selectObject("/config/db-info/user-name");  
  17.         Element passwordElt = (Element)doc.selectObject("/config/db-info/password");  
  18.         ........          
  19.         //读取出这些信息后可以设置到一个数据库配置信息实体类中,或进行其他操作。  
  20.           
  21.     } catch (DocumentException e) {  
  22.         e.printStackTrace();  
  23.     }             
  24. }  


2、从配置文件反射Dao层类:
xml配置文件:
[html]  view plain  copy
  1. <config>  
  2.     <dao-factory>  
  3.         <item-dao-facotry>com.bjpowernode.drp.basedata.dao.ItemDaoFactory4Oracle</item-dao-facotry>  
  4.       
  5.         <user-dao-facotry>com.bjpowernode.drp.basedata.dao.UserDaoFactory4Oracle</user-dao-facotry>  
  6.     </dao-factory>  
  7. </config>  



循环读取dao-factory下的item-dao-factory节点到一个Map中:
[java]  view plain  copy
  1. //保存dao工厂的名称  
  2. //key=名称,value=具体类完整路径  
  3. private Map<String, String> daoFactoryMap = new HashMap<String, String>();  


doc是Document对象,读取方法同上面的例子
[java]  view plain  copy
  1. //取得DaoFactory信息  
  2. List daoFactorylist = doc.selectNodes("/config/dao-factory/*");  
  3.   
  4.   
  5. for (int i=0; i<daoFactorylist.size(); i++) {  
  6.     Element daoFactoryElt = (Element)daoFactorylist.get(i);  
  7.     String tagName = daoFactoryElt.getName();  
  8.     String tagText = daoFactoryElt.getText();  
  9.     System.out.println("读取DaoFactory-->>" + tagText);  
  10.       
  11.     //放入到Map中  
  12.     daoFactoryMap.put(tagName, tagText);  
  13.       
  14.       
  15. }  

document的selectNodes()返回某个节点的子节点集合。

总结:
  dom4j是java中解析xml的一个组件,xPath用于xml文件节点的选择,具有多种匹配模式:路径、属性、位置、关系、函数等。
  针对常见的xml文件的解析可以封装到一个类中,类似sqlHelp的封装,完成对xml文件的ACID,遍历修改等操作。

  还有其他的对xml解析方法,如:使用dom方法、SAX方式。不再详述。


转自:http://blog.csdn.net/lmdcszh/article/details/9236427

猜你喜欢

转载自blog.csdn.net/ExceptionMapping/article/details/78468199