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 リクエストは非常に貪欲であり、たとえば、次のスニペットでは一致しないinputa に関連付けられたすべての要素と一致するとは限りません。labelinput

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

1 つの xpath 要求でより効率的な解決策が見つかる場合もありますが、複数の要求を行うことを検討する必要があります。
たとえば、「Add to Watchlist」というテキストを含む要素のすべてforの属性値を検索する 1 つの要求と、関連する要素を検索する別の要求を実行するとします。また、リクエストを基になる要素のスコープに制限する必要があります。時間があれば、より良いリクエストで編集するかもしれません。labelinputform

編集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 に答える