什么是 XPath?
- XPath 使用路径表达式在 XML 文档中进行导航
- XPath 包含一个标准函数库
- XPath 是 XSLT 中的主要元素
- XPath 是一个 W3C 标准
XPath 路径表达式
XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常相似。
XPath 标准函数
XPath 含有超过 100 个内建的函数。这些函数用于字符串值、数值,日期和时间比较、节点和 QName 处理、序列处理、逻辑值等等。
二 XPath术语
这部分是照本宣科,参考:http://www.w3school.com.cn/xpath/xpath_nodes.asp
先参考一个xml文档,如下:
<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
<list>
<book>
<title language="en">Think in Java</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</book>
</list>
</root>
1.节点(Node)
在 XPath 中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档(根)节点。XML 文档是被作为节点树来对待的。树的根被称为文档节点或者根节点。
在上面的例子中,<root>节点被成为文档节点,<book>节点是元素节点,language="en"是属性节点。
2.基本值(或称原子值,Atomic value)
基本值是无父或无子的节点。
示例:Think in Java,en都是原子节点。
3.节点关系
节点之间存在如下几种关系,字面意思很明白了,就不作解释了。
(1).父(Parent)
(2).子(Children)
(3).同胞(Sibling)
(4).先辈(Ancestor)
(5).后代(Descendant)
三 XPath的语法
XPath 使用路径表达式来选取 XML 文档中的节点或节点集。节点是通过沿着路径 (path) 或者步 (steps) 来选取的。
1.位置路径表达式
位置路径可以是绝对的,也可以是相对的。
绝对路径起始于正斜杠( / ),而相对路径不会这样。在两种情况中,位置路径均包括一个或多个步,每个步均被斜杠分割。
下面列出了最常用的路径表达式
表达式
描述
nodename 选取此节点的所有子节点
/ 从根节点选取
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的
. 选取当前节点
.. 选取当前节点的父节点
@ 选取属性
2.谓语
谓语用来查找某个特定的节点或者包含某个指定的值的节点。谓语被嵌在方括号中。
示例:
//list/book[1]:提取list节点下的第一个book节点
//list/book[last()]:提取list节点下的最后一个book节点
//title[@language=''en'']:提取language属性等于en的title节点
3.选取未知节点
XPath 通配符可用来选取未知的 XML 元素。
通配符
描述
* 匹配任何元素节点
@* 匹配任何属性节点
node() 配任何类型的节点
4.XPath轴
轴可定义某个相对于当前节点的节点集。
轴名称
结果
ancestor 选取当前节点的所有先辈(父、祖父等)
ancestor-or-self 选取当前节点的所有先辈(父、祖父等)以及当前节点本身
attribute 选取当前节点的所有属性
child 选取当前节点的所有子元素。
descendant 选取当前节点的所有后代元素(子、孙等)。
descendant-or-self 选取当前节点的所有后代元素(子、孙等)以及当前节点本身。
following 选取文档中当前节点的结束标签之后的所有节点。
namespace 选取当前节点的所有命名空间节点
parent 选取当前节点的父节点。
preceding 选取文档中当前节点的开始标签之前的所有节点。
preceding-sibling 选取当前节点之前的所有同级节点。
self 选取当前节点。
5.步(step)
步(step)包括:
轴(axis):定义所选节点与当前节点之间的树关系
节点测试(node-test):识别某个轴内部的节点
零个或者更多谓语(predicate): 更深入地提炼所选的节点集
步的语法:
轴名称::节点测试[谓语]
示例:例子
结果
child::book 选取所有属于当前节点的子元素的 book 节点
attribute::languane 选取当前节点的 languange 属性
child::* 选取当前节点的所有子元素
attribute::* 选取当前节点的所有属性
child::text() 选取当前节点的所有文本子节点
child::node() 选取当前节点的所有子节点
descendant::book 选取当前节点的所有 book 后代
ancestor::book 选择当前节点的所有 book 先辈
四.XPath运算符
XPath支持的运算主要有加、减、乘、除、模、与、或及相关比较运算(如:等于,大于,小于等),具体可以参考http://www.w3school.com.cn/xpath/xpath_operators.asp
五.相关函数
XPath支持的函数很多,具体可以参考:http://www.w3school.com.cn/xpath/xpath_functions.asp
文章出处:DIY部落(http://www.diybl.com/course/1_web/webjs/200855/114111.html)
例子:使用XPath就是为了快速定位,不需要我们为了在一个庞大的XML中为了找到一个节点而在代码中手动找到根节点,父节点,子节点,子节点,子节点的子。。。。等,主要我们xPath表达式写的好,那么就能提高解析XML的效率
在解析XML字符串的时候,一般就两种情况:
1,直接根据XML结构定位到唯一的节点
2,得到一个以某个元素为根的 list
import java.io.Reader;
import java.io.StringReader;
import java.util.List;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;
public class TextXPath
{
public static void main(String[] args) throws Exception{
// InputStream in = ClassLoader.getSystemResourceAsStream("win.ini");
// InputStream in = ClassLoader.getSystemResourceAsStream("testXpath.xml");
StringBuffer inputXML=new StringBuffer();
inputXML.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
inputXML.append("<ismpCreateSubscription>\n");
inputXML.append(" <system>\n");
inputXML.append(" <id>123</id>\n");
inputXML.append(" <passwd>321</passwd>\n");
inputXML.append(" </system>\n");
inputXML.append(" <streamingNo>290</streamingNo>\n");
inputXML.append(" <srcDeviceType>123</srcDeviceType>\n");
inputXML.append(" <srcDeviceID>41010300</srcDeviceID>\n");
inputXML.append(" <OA>92010010</OA>\n");
inputXML.append(" <OAType>3233</OAType>\n");
inputXML.append(" <DA>0</DA>\n");
inputXML.append(" <DAType>3</DAType>\n");
inputXML.append(" <PProductOfferID>3</PProductOfferID>\n");
inputXML.append(" <FA>3</FA>\n");
inputXML.append(" <FAType>3</FAType>\n");
inputXML.append(" <PackageIDList>\n");
inputXML.append(" <item language='3'>\n");
inputXML.append(" <PackageID>123</PackageID>\n");
inputXML.append(" <PackageValue>aaa</PackageValue>\n");
inputXML.append(" </item>\n");
inputXML.append(" <item language='5'>\n");
inputXML.append(" <PackageID>456</PackageID>\n");
inputXML.append(" <PackageValue>bbb</PackageValue>\n");
inputXML.append(" </item>\n");
inputXML.append(" <item language='6'>\n");
inputXML.append(" <PackageID>789</PackageID>\n");
inputXML.append(" <PackageValue>ccc</PackageValue>\n");
inputXML.append(" </item>\n");
inputXML.append(" </PackageIDList>\n");
inputXML.append("</ismpCreateSubscription>\n");
Reader in = new StringReader(inputXML.toString());
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(in);
Element root=doc.getRootElement();
// List<Element> list = (List<Element>)XPath.selectNodes(root, "//PackageIDList/item[@language = 2]");
/*得到元素list*/ List<Element> list = (List<Element>)XPath.selectNodes(root, "//PackageIDList/item");
System.out.println(list.size());
for(int i=0;i<list.size();i++)
{
System.out.println(list.get(i).getChildText("PackageValue"));
}
/*得到唯一元素*/ Element e=(Element)XPath.selectSingleNode(root, "//streamingNo");
System.out.println(e.getTextTrim());
}
}
输出:
3
aaa
bbb
ccc
290
//PackageIDList/item[last()]
选取属于 PackageIDList子元素的最后一个 item元素。
//PackageIDList/item[last()-1]
选取属于 PackageIDList子元素的倒数第二个 item元素。
//PackageIDList/item[position()<3]
选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
//PackageIDList/item[@language ='2' and contains(@title, 'Java')]
选取language 为1,标题中含有Java的book元素。
//PackageIDList/item[@language = 2]
选取language 为2,标题中含有的item元素。
总结: 解析XML主要用到 JDOM的
XPath.selectNodes()
XPath.selectSingleNode()
这两个函数