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、读取文档:

	 private File inputXml;
	 public Document getDocument() {
	        SAXReader saxReader = new SAXReader();
	        Document document = null;
	        try {
	            document = saxReader.read(inputXml);
	        } catch (DocumentException e) {
	            e.printStackTrace();
	        }
	        return document;
	     }

2、获取跟节点:

    public Element getRootElement() {
       return getDocument().getRootElement();
    }

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

	Element root = getRootElement();
	
	for (Iterator ie = root.elementIterator(); ie.hasNext();) {
            System.out.println("======");
            Element element = (Element) ie.next();
            System.out.println(element.getName());
	}

4、枚举所有属性节点:

 for (Iterator ia = element.attributeIterator(); ia.hasNext();) {
              Attribute attribute = (Attribute) ia.next();
              System.out.println(attribute.getName() + ":"
                     + attribute.getData());
    }

5、枚举当前节点下的所有子节点:
 for (Iterator ieson = element.elementIterator(); ieson.hasNext();) {
              Element elementSon = (Element) ieson.next();
              System.out.println(elementSon.getName() + ":"
                     + elementSon.getText());
 }

6、获取并遍历某个节点下的所有子节点: 
                      List daoFactorylist = doc.selectNodes("/config/dao-factory/*");
			
			
			for (int i=0; i<daoFactorylist.size(); i++) {
				Element daoFactoryElt = (Element)daoFactorylist.get(i);
				String tagName = daoFactoryElt.getName();
				String tagText = daoFactoryElt.getText();
				System.out.println("读取DaoFactory-->>" + tagText);
				
				//放入到Map中
				daoFactoryMap.put(tagName, tagText);
				
				
			}


二、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树为例说明几种解析匹配模式:
 

         <A id="a1">
           <B id="b1">
                 <C id="c1">
                   <B name="b"/>
                   <D id="d1"/>
                   <E id="e1"/>
                   <E id="e2"/>
                 </C>
           </B>
           <B id="b2"/>
           <C id="c2">
                 <B/>
                 <D id="d2"/>
                 <F/>
           </C>
           <E/>
         </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文件:

<?xml version="1.0" encoding="UTF-8"?>
<config>
	<db-info>
		<driver-name>oracle.jdbc.driver.OracleDriver</driver-name>
		<url>jdbc:oracle:thin:@localhost:1521:orcl</url>
		<user-name>drp1</user-name>
		<password>drp1</password>
	</db-info>


</config>


XmlConfigReader类的构造函数:
	private XmlConfigReader() {
		
		
		SAXReader reader = new SAXReader();
		
		InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("sys-config.xml");
		try {
						   
			
			
			Document doc = reader.read(in);
			
			//取得jdbc相关配置信息
			Element driverNameElt = (Element)doc.selectObject("/config/db-info/driver-name");
			Element urlElt = (Element)doc.selectObject("/config/db-info/url");
			Element userNameElt = (Element)doc.selectObject("/config/db-info/user-name");
			Element passwordElt = (Element)doc.selectObject("/config/db-info/password");
			........		
			//读取出这些信息后可以设置到一个数据库配置信息实体类中,或进行其他操作。
			
		} catch (DocumentException e) {
			e.printStackTrace();
		}			
	}
	


2、从配置文件反射Dao层类:
xml配置文件:
<config>
	<dao-factory>
		<item-dao-facotry>com.bjpowernode.drp.basedata.dao.ItemDaoFactory4Oracle</item-dao-facotry>
	
		<user-dao-facotry>com.bjpowernode.drp.basedata.dao.UserDaoFactory4Oracle</user-dao-facotry>
	</dao-factory>
</config>



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


doc是Document对象,读取方法同上面的例子
			//取得DaoFactory信息
			List daoFactorylist = doc.selectNodes("/config/dao-factory/*");
			
			
			for (int i=0; i<daoFactorylist.size(); i++) {
				Element daoFactoryElt = (Element)daoFactorylist.get(i);
				String tagName = daoFactoryElt.getName();
				String tagText = daoFactoryElt.getText();
				System.out.println("读取DaoFactory-->>" + tagText);
				
				//放入到Map中
				daoFactoryMap.put(tagName, tagText);
				
				
			}

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

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



你可能感兴趣的:(dom4j解析xml详解)