0

我有一个很大的 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[label[contains(text(),'Add to Watchlist')]]

只会给子标签的父div。我试图从这个片段的最顶层节点开始

$x("//div[@class='x-column-inner' and //label[contains(text(),'Add to Watchlist')]]")

但这给出了 6 个可能的匹配项。

注意:不能使用@id 属性,因为这是动态分配给节点的,所以下次页面加载时@id 会有所不同。我不想使用 position() 谓词,因为这会使 XPATH 静态,并且 xpath 可能会随着位置的任何变化而中断。

4

1 回答 1

0

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

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

但是,您的代码段并不有趣,不会input匹配任何标签,请考虑提供更好的代码段。它将提高答案的准确性。

编辑:这是添加“添加到监视列表”约束的(未经测试的)方法。

//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 请求非常贪婪,并且不能保证您匹配input与 a 关联的每个元素label,例如以下input代码段中将不匹配:

<div>
  <div>
    <label for="id">Add to Watchlist</label>
  </div>
  <div>
    <input type="checkbox" id="id" />
  </div>
<div>

在一个 xpath 请求中可能有更有效的解决方案,但您应该考虑执行多个请求。
例如,一个请求查找具有文本“添加到监视列表”for的元素的每个属性值,label然后执行另一个请求以查找关联的input元素。我还应该尝试将您的请求限制在基础form元素的范围内。如果我有时间,也许我会提出更好的要求进行编辑。

编辑 2 这是一个有效且更智能的请求

//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>

胸围最重要的是您了解它是如何工作的以及为什么它更好。请花点时间考虑一下。

于 2013-01-15T20:59:26.470 回答