xml – 为什么XPath不干净?为什么谓词中不需要text()?

前端之家收集整理的这篇文章主要介绍了xml – 为什么XPath不干净?为什么谓词中不需要text()?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
假设我有:
<A>
  <B>C</B>
  <D>E</D>
</A>

然后我可以输出B元素(包括标签):

//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(),但谓词不需要它?

我认为这是一个合理而自然的问题.我宁愿看到人们提出像这样的概念性问题来理解XPath是如何工作的,而不是解决对XPath的浅层理解,最后问一些浅薄的问题,为什么他们的XPath表达式没有按照他们在从某个Web上抓取数据时所做的那样做页.

我们先来澄清一些术语.通过“输出”,我假设你的意思与“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”.

原文链接:https://www.f2er.com/xml/293112.html

猜你在找的XML相关文章