JavaEE XML XPath
@author ixenos
XPath技术
1 引入
问题:当使用dom4j查询比较深的层次结构的节点(标签,属性,文本),比较麻烦!!!需要遍历DOM树的众多节点来进行查找!
比如rootEle.element(“dsfs”).element(“sdfsf”)element(“sdfsf”). element(“aim”)
2 xPath作用
主要是用于快速获取所需的节点对象。
(XSLT中的match属性的值就使用XPath!!!)
3 在dom4j中如何使用xPath技术
1)导入xPath支持jar包 。 jaxen-1.1-beta-6.jar
2)使用xpath方法
List<Node> selectNodes("xpath表达式"); 查询多个节点对象
Node selectSingleNode("xpath表达式"); 查询一个节点对象
4 xPath语法
/ 绝对路径 表示从xml的根位置开始或子元素(一个层次结构)
// 相对路径 表示不分任何层次结构的选择元素。
* 通配符 表示匹配所有元素
[] 条件 表示选择什么条件下的元素
@ 属性 表示选择属性节点
and 关系 表示条件的与关系(等价于&&)
text() 文本 表示选择文本内容
示例:
XPath可以描述XML文档中的一个节点集
/grib/row
描述了grib的子元素(每一个grib)中所有的row元素
/grib/row[1]
用[]选择特定元素,这表示第一行(索引从1开始)
/grib/row[1]/cell[1]/@anchor
用@得到属性值,这描述了第一行第一个单元格的anchor属性
/grib/row/cell/@anchor
描述了作为根元素的grib的子元素的那些row元素中所有cell的anchor属性
/**
* 1. / 绝对路径 表示从xml的根位置开始或子元素(一个层次结构)
*/
xpath = "/contactList";
xpath = "/contactList/contact"; /**
* 2. // 相对路径 表示不分任何层次结构的选择元素。
*/
xpath = "//contact/name";
xpath = "//name"; /**
* 3. * 通配符 表示匹配所有元素
*/
xpath = "/contactList/*"; //根标签contactList下的所有子标签
xpath = "/contactList//*";//根标签contactList下的所有标签(不分层次结构) /**
* 4. [] 条件 表示选择什么条件下的元素
*/
//带有id属性的contact标签
xpath = "//contact[@id]";
//第二个的contact标签
xpath = "//contact[2]";
//选择最后一个contact标签
xpath = "//contact[last()]"; /**
* 5. @ 属性 表示选择属性节点
*/
xpath = "//@id"; //选择id属性节点对象,返回的是Attribute对象
xpath = "//contact[not(@id)]";//选择不包含id属性的contact标签节点
xpath = "//contact[@id='002']";//选择id属性值为002的contact标签
xpath = "//contact[@id='001' and @name='eric']";//选择id属性值为001,且name属性为eric的contact标签 /**
*6. text() 表示选择文本内容
*/
//选择name标签下的文本内容,返回Text对象
xpath = "//name/text()";
xpath = "//contact/name[text()='张三']";//选择姓名为张三的name标签
更多XPath表达式请看XPath Tutorial
Demo:
import java.io.File;
import java.io.FileOutputStream; import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter; /**
* 第一个xpath程序
* @author ixenos
*
*/
public class Demo1 { public static void main(String[] args) throws Exception{
/**
* 需求: 删除id值为2的学生标签
*/
Document doc = new SAXReader().read(new File("e:/student.xml")); //1.查询id为2的学生标签
//使用xpath技术
Element stuElem = (Element)doc.selectSingleNode("//Student[@id='2']"); //2.删除标签
stuElem.detach(); //3.写出xml文件
FileOutputStream out = new FileOutputStream("e:/student.xml");
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("utf-8");
XMLWriter writer = new XMLWriter(out,format);
writer.write(doc);
writer.close();
} }
简要示例
1) 用XPath定位标签,进行修改操作
package com.ixenos.xpath; import java.util.List; import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader; import com.ixenos.dom4j.CreateXML; /**
* 在TestXPath的基础上改进了:
* 将精准定位全交给XPath去做,因此删除了modEle多余的属性定位判断
*
* @author ixenos
*
*/
public class TestXPath2 { /**
* 读取XML文件生成Docment
*
* @throws Exception
*/
public static Document getDoc(String path) throws Exception {
Document doc = new SAXReader().read(path);
return doc;
} /**
* XPath定位标签
*/
@SuppressWarnings("unchecked")
public static List<Element> getEle(Document doc, String xpath) {
return (List<Element>)doc.selectNodes(xpath);
} /**
* 对指定标签的子节点进行修改
*
* @param func
* 修改功能选择
* @param eleList
* 被修改的标签list
* @param aimChild
* 想要修改的子标签
* @param aimChildText
* 想要修改的新的子标签文本值
*/
public static void modEle(String func, List<Element> eleList, String aimChild, String aimChildText) {
// 取出
for (Element ele : eleList) {
// 修改功能选择
if ("delete".equals(func)) {
ele.detach();
} else if ("modify".equals(func)) {
// 修改指定子节点的文本值
// element(name)指定第一个标签名为name的标签
// setText修改Text,addText追加Text
ele.element(aimChild).setText(aimChildText);
}
} } /**
* 将DOM树输出为XML文件
*
* @throws Exception
*/
public static void writeXML(Document doc, Boolean pretty, String encoding) throws Exception {
CreateXML.writeXML(doc, pretty, encoding);
} /**
* 测试
*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
Document doc = getDoc("demo.xml"); //得到所有id属性值为2的Student标签
List<Element> eleList = getEle(doc, "//Student[@id='2']"); modEle("modify", eleList, "name", "尔雅");
// modEle("delete", eleList, null, null);
writeXML(doc, true, "utf-8"); }
}
修改结果:
<?xml version="1.0" encoding="utf-8"?> <Students>
<Student id="1">
<name>张三</name>
<gender>男</gender>
<grade>物联网一般</grade>
<address>广州白云</address>
</Student>
<Student id="2">
<name>尔雅</name>
<gender>女</gender>
<grade>物联网二班</grade>
<address>广州海珠</address>
</Student>
</Students>
2) 用XPath读取一个规范的html文件(比如xhtml)
import java.io.File;
import java.util.Iterator;
import java.util.List; import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader; /**
* 使用xpath技术读取一个规范的html文档
* @author ixenos
*
*/
public class Demo4 { public static void main(String[] args) throws Exception{
Document doc = new SAXReader().read(new File("./src/personList.html"));
//System.out.println(doc); //读取title标签
Element titleElem = (Element)doc.selectSingleNode("//title");
String title = titleElem.getText();
System.out.println(title); /**
* 练习:读取联系人的所有信息
* 按照以下格式输出:
* 编号:001 姓名:张三 性别:男 年龄:18 地址:xxxx 电话: xxxx
* 编号:002 姓名:李四 性别:女 年龄:20 地址:xxxx 电话: xxxx
* ......
*/
//1.读取出所有tbody中的tr标签
List<Element> list = (List<Element>)doc.selectNodes("//tbody/tr");
//2.遍历
for (Element elem : list) {
//编号
//String id = ((Element)elem.elements().get(0)).getText();
String id = elem.selectSingleNode("td[1]").getText();
//姓名
String name = ((Element)elem.elements().get(1)).getText();
//性别
String gender = ((Element)elem.elements().get(2)).getText();
//年龄
String age = ((Element)elem.elements().get(3)).getText();
//地址
String address = ((Element)elem.elements().get(4)).getText();
//电话
String phone = ((Element)elem.elements().get(5)).getText(); System.out.println("编号:"+id+"\t姓名:"+name+"\t性别:"+
gender+"\t年龄:"+
age+"\t地址:"+address+
"\t电话:"+phone);
}
}
}