<A> <B>C</B> <D>E</D> </A>
//B
哪个会回归
<B>C</B>
但是为什么谓词中不需要text()?以下2行给出相同的输出:
/A[B = 'C']/D /A[B/text() = 'C']/D
如果XPATH是干净的构造我会期望它(或在某种其他元素结构):
/A[B = <B>C></B>]/D
和:
/A[B/text()='C']/D
有人可以给我一个理由,为什么输出需要text(),但谓词不需要它?
我们先来澄清一些术语.通过“输出”,我假设你的意思与“return”相同:XPath表达式选择的值. (XPath本身没有直接输出功能.)
通过“干净的构造”,我将假设你的意思是“简单而一致的设计”.
简短的回答是XPath是一致的,但是像大多数灵活而强大的工具一样,它并不简单.
接下来,我们可能需要询问您正在考虑的XPath版本.版本1,2和3之间存在很大差异.我将重点关注XPath 1.0,因为它是最知名且广泛实现的,我也不知道2.0或3.0.
无论它是否在谓词中,B都意味着相同的事情.在// B和in / A [B =’C’]中,它都是node test.它匹配(选择)名为B的元素节点.XPath对标签一无所知.它在抽象树文档模型上运行. XPath表达式可以选择元素和其他节点,但不能选择标记.
所以我认为你的问题会减少,为什么/ A [B =’C’] / D成功选择你提供的XML样本中的D元素,当B选择一个元素而不仅仅是文本’C’?为了进一步减少它,为什么B =’C’对于元素A的评估为真,当B是一个元素而不仅仅是一个包含’C’的文本节点?
答案是,when performing comparisons如=,
If one object to be compared is a node-set and the other is a string,
then the comparison will be true if and only if there is a node in the
node-set such that the result of performing the comparison on the
string-value of the node and the other string is true [emphasis added].
换句话说,子表达式B可以在这里选择多个元素节点,如果/ A有多个名为B的子元素.(在这种情况下,只有一个这样的子元素.)要计算表达式B =’C’,XPath查看B. According to the docs选择的每个节点的字符串值,
The string value of an element node is the concatenation of the string-values of all text node descendants of the element node in document order.
在这种情况下,B元素节点的唯一文本节点后代是其字符串值为“C”的文本节点.因此,B的字符串值是’C’,因此对于元素/ A,谓词[B =’C’]为真.
为什么XPath以这种方式定义元素节点的字符串值?我猜它部分是因为单文本节点的方便性,但是当涉及到自由格式的标记文本时,就像
<p>HTML that <em>could</em> have <b>arbitrary <tt>nesting</tt></b></p>
对于某些目的,您有时希望忽略其标记,快速检索所有后代文本节点的串联可能非常方便.
问题的另一部分是,你为什么不写
/A[B = <B>C</B>]/D
要么
/A[B/text()='C']/D
第二个答案最短:你可以.它只是不太方便,功能也不那么强大,但它更加明确和精确.它不会一直给你相同的结果,因为这个版本不会询问B的字符串值;它询问(任何)B是否具有值为“C”的任何文本节点子节点,而不是询问是否有任何B具有产生“C”的所有后代文本节点的串联.
至于/ A [B =< B> C< / B>] / D,XPath(至少1.0)没有设计具有用于创建新节点的语法,例如< B> C< / B>.但即使它是,B =< B> C< / B>意思?你显然不是要求进行身份比较,而是要求一种结构等同. XPath定义器必须创建比较语义,其中两个节点集之间或节点集和新定义类型(例如“结构模板”)之间的比较为真,当且仅当(例如)存在时(第一个)节点集中的节点,递归地匹配结构模板的结构,或第二个节点集中的节点的结构.但相反they defined it as follows,
If both objects to be compared are node-sets,then the comparison will be true if and only if there is a node in the first node-set and a node in the second node-set such that the result of performing the comparison on the string-values of the two nodes is true.
鉴于他们只能选择两个定义中的一个来比较节点集,为什么他们选择后者而不是你期望的定义呢?我不知道XPath委员会的会议记录,但我怀疑它归结为后者的定义更符合他们分析的最常见的用例,同时还考虑了性能和实现的简单性.
我同意这个定义不是定义=比较最明显的方法.但我认为设计人员是正确的,比较整个节点树结构并不是一个非常常见的用例,而常见的用例(例如你提供的用例)很好地被XPath提供的工具所覆盖.例如,在XPath中非常简单地询问是否存在作为根节点的子元素的A元素,其具有子B元素,其文本值(暂时忽略所有子标记)为“C”.