xpath介绍之谓词、函数、路径操作符和通配符
在xpath路径表达式中,可在适当的地方加上限制谓词,用[]括起。
用来说明的代码段
<?xml version="1.0" encoding="UTF-8" ?>
<wsd:definitions name="BillingService"
targetNamespace="http://www.ElectricSupplyCompany.com/BillingService-interface"
xmlns:wsd="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://www.ElectricSupplyCompany.com/BillingService"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<message name="MonthNumber">
<part name="number" type="xsd:int"/>
</message>
<message name="TotalBill">
<part name="bill" type="xsd:int"/>
</message>
<portType name="BillingService_port">
<operation name="getBillForMonth">
<input message="MonthNumber"/>
<output message="TotalBill"/>
</operation>
<operation name="getCurrentBill">
<output message="TotalBill"/>
</operation>
</portType>
<binding name="BillingService_Binding" type="BillingService_port">
<soap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http" />
<operation name="getBillForMonth">
<soap:operation soapAction="urn:BillingService" />
<input>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:BillingService"
use="encoded" />
</input>
<output>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:BillingService"
use="encoded" />
</output>
</operation>
<operation name="getCurrentBill">
<soap:operation soapAction="urn:BillingService" />
<input>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:BillingService"
use="encoded" />
</input>
<output>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:BillingService"
use="encoded" />
</output>
</operation>
</binding>
<service name="BillingService">
<documentation> Billing Service of Electric Supply Company. </documentation>
<port binding="BillingService_Binding" name="BillingService_ServicePort">
<soap:address location="http://localhost:8080/soap/servlet/rpcrouter" />
</port>
</service>
</wsd:definitions>
让我们从一个将返回任何XML文件当中的根节点的简单查询开始:
./node()
我们可以更进一步,使用另一个简单查询,选择根节点的全部的直接子节点:
./node()/*
如果你想要得到所有的是根节点的直接子节点并且只有一个type属性的节点,那么该怎么办呢? 那么就使用下面的这个查询:
./node()/*[attribute::type]
在代码段1中,这个查询将返回binding元素。 由此可见,写在方括号之内的代码attribute::query担负一个过滤器的功能。 XPath中的过滤器被称作谓词(predicate),写在方括号内。 一个谓词作用在一个结点集上--在这个例子中,结点集由根节点的所有的直接子节点组成---应用过滤条件(在这里,结点肯定有一个type属性)到结点集上。 产生的结果就是一个经过过滤的结点集。
谓词可以从简单到很复杂。 也许XPath谓词的简单形式就像下面的查询中的只是一个数字,返回根元素的第二个子节点(message元素):
./node()/*[2]
查询语句./node()/message[attribute::name="TotalBill"]/text() 将寻找根元素的一个属性name值为TotalBill的特定的message子节点。 查询将返回特定的message元素的所有文本结点。 这个查询将返回代码段1中两个message元素中的第二个。
XPath 函数
xpath允许多种函数。
last()函数
last()函数将总是指向结点集的最后一个结点。
./node()/message[last()]
注意下面的这条查询也返回相同的message元素:
./node()/message[2]
这两个查询之间唯一的区别就是我们使用数字2来代替last()方法。
last()函数总是返回一个数字。
position()函数
./node()/message[1]/part
./node()/message[2]/part
./node()/message[3]/part
它们将分别返回message元素的第一个、第二个和第三个part子元素。 由此可见节点集中的每个节点都有一个位置。 第一个节点的位置是1,第二个节点的位置是2,以此类推。
如果你想要得到除第二个以外的所有的message元素,你该怎么办? 你可以使用position()函数取得一个节点的位置。 下面的这条查询将返回代码段2中的第一个和第三个message元素:
./node()/message[position()!=2]
position()函数只是返回指定值所表示的节点的位置。 谓词[position()!=2] 把所有的message元素的位置和2做比较,然后找出位置不是2的节点。
count()函数
代码段1中的portType元素有多少个message子元素? 数一数你就发现有两个message元素。 在XPath中解决"多少个"这种问题是一个二步的操作。 首先,写一个用来找到你想要统计的所有的子元素的XPath查询。 然后地像下面给出的那样,把 XPath查询传送到count()函数中:
步骤1: ./node()/message
步骤2: count(./node()/message)
count()函数统计XPath查询所得到的节点集中的节点数,并返回这个节点数。
name()、local-name()和namespace-uri()函数
./node()/*[5]
它返回根元素的第五个子元素。 service元素本身是一个完整结构,也包含子元素。 因此,这个XPath查询的返回值实际上是一个XML节点而不仅仅是一个元素名。
name()函数返回XML节点的名称。 例如,下面的查询应用到代码段1中将返回字符串"service":
name(./node()/*[5])
同样,下面的查询将返回字符串"wsd:definitions"(使用域名空间前缀的根元素的全名):
name(./node())
local-name()和namespace-uri()函数与name()函数类似,除了local-name方法只返回不带域名空间前缀的元素的局部名称,而namespace-uri函数仅仅返回域名空间URI。举例来说,请在代码段1中试验下面的查询:
local-name(./node())
namespace-uri(./node())
第一个查询返回一个字符串" definitions",而第二个查询返回" http://schemas.xmlsoap.org/wsdl/ "。
String函数
我们已经知道name()、local-name()和namespace-uri()函数返回字符串。 XPath提供了许多函数用于处理字符串,比如string()、 substring()、substring-before()、 substring-after()、 concat()、starts-with()等等。 下面给出了一个例子来演示一下如何使用string()函数:
string(./node()/*[2]/part/attribute::name)
上面的这条查询将寻找根元素的第二个子元素,然后它将得到根元素的第二子元素的所有的part子元素。 接着它将寻找part子元素的name属性,最后它把name属性的值转换为一个字符串格式。 当把这条语句应用到代码段1中的时候,它将输出bill。
XPath也提供一些布尔函数,返回"true/false",研究一下下面的这条查询:
boolean(./node()/message)
当把它应用到代码段1的时候,它返回true。 这是因为boolean()函数判断一个XPath查询产生的节点集是否为空(在我们的例子中,根元素包含两个message子元素)。 如果是空,boolean()函数返回false,否则返回true。
first()类似于last()函数。得到对象中的第一个。
xpath路径操作符
/ 跟节点
. 当前节点
.. 当前节点的父节点
// 整个文档树
通配符号 *可表示取所有子元素。
./node()/*
