contains()在XPath中做了什么?

eph*_*ris 4 xml xpath

我有两个几乎相同的表,唯一的区别是第一个中的输入标记:

表格1

  <table>
    <tbody>
      <tr>
        <td>
          <div>
            <input type="text" name="" value=""/>
          </div>
        </td>
      </tr>
    </tbody>
  </table>
Run Code Online (Sandbox Code Playgroud)

表#2

  <table>
    <tbody>
      <tr>
        <td>
          <div></div>
        </td>
      </tr>
    </tbody>
  </table>
</body>
Run Code Online (Sandbox Code Playgroud)

当我使用这个XPath时,//table//tbody//tr[position()=1 and contains(.,input)]它返回两个表的第一行,而不仅仅是我期望的第一个表第一行.

但是,这个XPath //table//tbody//tr[position()=1]//input只返回input第一个.

那么,我做错了什么?为什么input两个表都相同?我.在某种程度上误用了这里吗?

kjh*_*hes 7

由于函数名称1的不幸选择,许多人误以为contains()XPath中函数的用途:

  • 的XPath contains()不会检查元素 遏制.
  • XPath contains()检查子字符串包含.

因此,tr[contains(.,input)]不会做你认为它做的事情.它实际上选择tr了其string-value包含一个子串的元素,该子串等于第一个直接子input元素的string-value ; 有关详细信息,请参阅此答案.(有趣的是,这样的谓词简化为true,因为字符串值定义的分层特性意味着父元素和子元素的字符串值之间的子字符串包含.)无论如何,这显然不是你的意图.

要检查后代元素包含,请.//input改用.这可以tr作为第一个XPath尝试执行的谓词,如果它tr是您想要选择的元素,

//table//tbody//tr[position()=1 and .//input]
Run Code Online (Sandbox Code Playgroud)

或者table(如@Andersson所示),如果它table是你想要选择的包含input后代元素的元素:

//table[.//input]
Run Code Online (Sandbox Code Playgroud)

为什么XPath contains()应该被命名string-contains()

1在XML的上下文中,它强烈地基于层次结构的概念,很自然地假设contains是指层次包含.在最初的XPath规范中,单词包含的24次出现,其中19次表示分层节点包含; 只有5次意味着子串遏制.毫无疑问contains()存在混淆.XPath子字符串contains()函数应该被命名为string-contains().