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;
}
public Element getRootElement() {
return getDocument().getRootElement();
}
Element root = getRootElement();
for (Iterator ie = root.elementIterator(); ie.hasNext();) {
System.out.println("======");
Element element = (Element) ie.next();
System.out.println(element.getName());
}
for (Iterator ia = element.attributeIterator(); ia.hasNext();) {
Attribute attribute = (Attribute) ia.next();
System.out.println(attribute.getName() + ":"
+ attribute.getData());
}
for (Iterator ieson = element.elementIterator(); ieson.hasNext();) {
Element elementSon = (Element) ieson.next();
System.out.println(elementSon.getName() + ":"
+ elementSon.getText());
}
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)用“/”指示节点路径
如“/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>
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(); } }
<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工厂的名称 //key=名称,value=具体类完整路径 private Map<String, String> daoFactoryMap = new HashMap<String, String>();
//取得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); }