如何为动态层次结构下的节点编写XPATH

如何为动态层次结构下的节点编写XPATH,xpath,Xpath,我得到了一个大的XML。该XML的一个片段如下所示: <div class="x-column-inner" id="ext-gen422" style="width: 850px;"> <div id="ext-comp-1206" style="width: 14px;" class=" x-column"> <div tabindex="-1" class="x-form-item x-hide-label" id="ext-gen434">

我得到了一个大的XML。该XML的一个片段如下所示:

<div class="x-column-inner" id="ext-gen422" style="width: 850px;">
 <div id="ext-comp-1206" style="width: 14px;" class=" x-column">
  <div tabindex="-1" class="x-form-item  x-hide-label" id="ext-gen434">
   <label class="x-form-item-label" style="width:100px;" for="ext-comp-1180" id="ext-gen435"></label>
  <div style="padding-left:105px" id="x-form-el-ext-comp-1180" class="x-form-element">
   <div class="x-form-check-wrap" id="ext-gen436" style="width: 14px; height: 28px;">
    <input type="checkbox" name="ext-comp-1180" id="ext-comp-1180" autocomplete="off" class=" x-form-checkbox x-form-field">
     <label class="x-form-cb-label" for="ext-comp-1180" id="ext-gen437">&nbsp;</label>
    </div></div>  <div class="x-form-clear-left">
    </div>
   </div>
  </div>
 <div id="ext-comp-1207" style="width: 150px;" class=" x-column">
  <label id="ext-comp-1203" style="width: 140px;">Add to Watchlist</label>
</div>
<div id="ext-comp-1208" style="width: 107px;" class=" x-column">
将只给出子标签的父div。 我试图从这个片段的最顶端节点开始

$x("//div[@class='x-column-inner' and //label[contains(text(),'Add to Watchlist')]]")
但这是6种可能的匹配

注意:@id属性无法使用,因为这将动态分配给节点,所以下次页面加载@id时会有所不同。
我不想使用position()谓词,因为这会使XPATH保持静态,XPATH可能会因位置的任何更改而中断。

您可以尝试类似的方法,但它看起来非常贪婪。。。基本上,它所做的是在
输入
标记的每个轴上搜索,以查看是否存在关联的
标签
标记。因此,对于每个
输入
,它都会搜索其祖先、后代和兄弟姐妹。 当然还有一些更聪明的解决方案

//input[@type = 'checkbox' and (@id = ancestor::label/@for or @id = descendant::label/@for or @id = following::label/@for or @id = preceding::label/@for)]

但是,你的代码片段并不有趣,没有代码>输入< /代码>标签,请考虑提供一个更好的代码片段。这将提高答案的准确性

编辑:以下是一种(未经测试的)添加“添加到观察列表”约束的方法

//input[@type = 'checkbox' and (@id = ancestor::label[. = 'Add to Watchlist']/@for or @id = descendant::label[. = 'Add to Watchlist']/@for or @id = following::label[. = 'Add to Watchlist']/@for or @id = preceding::label[. = 'Add to Watchlist']/@for)]
但是再一次,这些xpath请求非常贪婪,并且不能保证匹配与
标签
关联的每个
输入
元素,例如,以下
输入
在该代码段中不匹配:

<div>
  <div>
    <label for="id">Add to Watchlist</label>
  </div>
  <div>
    <input type="checkbox" id="id" />
  </div>
<div>
你可以面对这个片段

<html>
  <form>
    <label for="bar">Add to Watchlist</label>
    <div>
      <div>
        <label for="id">Add to Watchlist</label>
      </div>
      <div>
        <input type="checkbox" id="id" />
        <input type="checkbox" id="foo" />
        <input type="checkbox" id="bar" />
        <input type="checkbox" />
        <input type="checkbox" id="" />
      </div>
    </div>
  </form>
  <label for="foo">Add to Watchlist</label>
</html>

加入观察名单
加入观察名单
加入观察名单

最重要的是,你知道它是如何工作的,为什么它更好。请花点时间考虑一下。

您的输入和文档中的标签标签之间可能存在什么关系?另外,您想检索标签还是输入标签?似乎只有逻辑关系,因为标签是输入标签。我无法解释句法关系:(不考虑你的例子格式不正确,他们看起来是兄弟姐妹,所以有些事情你没有告诉我们。为错误的缩进道歉。我已经更正了一点。请原谅我的代码段。给出更大的代码段(即此代码段的超集)会更好吗?我没有添加太大的代码段,因为这会使问题变得更复杂sy.还有什么其他想法可以让代码片段更好地提高答案的准确性吗?谢谢。你应该创建一个简单的代码片段,其中一些
输入
节点将与xpath表达式匹配。你尝试过我的答案吗?谢谢Zoom。你的解决方案已经将节点缩小到xml中的两个复选框中。两个节点是:
>
现在,由于这两个节点都没有任何唯一的属性,除了dynamic@id之外,我需要求助于position()吗?我不明白您需要实现什么。找到的两个
input
标记已被选中,因为它们链接到另一个
标签
标记,该标签具有
for
属性,该属性与
input
标记的
id
属性匹配。这是您想要的吗?感谢您的时间和帮助。实际上我只想要
input
节点,该节点附加到特定的
标签
上,具有文本
添加到监视列表
,因此我将xpath修改为:
//输入[@type='checkbox'和(@id=concenter::label/@for或@id=following sibling::label/@for或@id=previous sibling::label/@for)和(following::label='Add to Watchlist'))
它成功了:)
//form//input[@type = 'checkbox' and @id = ancestor::form[1]//label[. = 'Add to Watchlist']/@for]
<html>
  <form>
    <label for="bar">Add to Watchlist</label>
    <div>
      <div>
        <label for="id">Add to Watchlist</label>
      </div>
      <div>
        <input type="checkbox" id="id" />
        <input type="checkbox" id="foo" />
        <input type="checkbox" id="bar" />
        <input type="checkbox" />
        <input type="checkbox" id="" />
      </div>
    </div>
  </form>
  <label for="foo">Add to Watchlist</label>
</html>