XPathとは

2023年1月14日

ブラウザ画面の要素を操作するためには、画面のHTML要素を一意に特定する必要があります。WingGoferでは要素を特定する方法としてXPathを使用します。

XPathとは

WebページはHTMLで記述され、ツリー状の構造となっています。XPathは、HTMLのツリー構造に着目して、要素を特定するための記述方法です。例えば以下のHTMLでは

HTML内容
<!DOCTYPE html>
<html>
 <head> <!-- ヘッダ部は画面に表示されません -->
  <title>サンプルページ</title>
  <style type="text/css">  
    .red{color: red;}
  </style>
 </head>
 <body>
  <div id="main_container">
   <h1>見出し</h1>
   <p>段落1</p>
   <p class="red">段落2</p>
   <p>段落3</p>
  </div>
  <div id="footer">
    <p>copyright</p>
  </div>
</body>
</html>

HTMLは要素をタグ「<>」で囲み、タグ内にさらにタグを入れることができます。したがってHTML文書はツリー構造となります。

画面上の表示
見出し

段落1

段落2

段落3

copyright

「段落2」をXPathで指定すると、最上位の<htm>タグから、<body>,<div>,<p>と順番に降りていって

/html/body/div[1]/p[2]

のようになります。
p[2]は2番目のp要素を表します。(1始まり)

ただし、上記のようなXPathでは、画面が変更された場合(例えば先頭に段落を追加した場合、対象のp要素は3番目になる)XPathも変更される可能性が高くなり、そのたびに操作シナリオに記入されたXPathを変更する必要があります。

属性での指定

そこで、HTML要素が持つ「id」や「class」などの属性でXPathを記述することができます。
上の例で、段落2には「class="red"」の指定があるので、

//p[@class="red"]

と記述することができます。値を囲む記号は「”(ダブルクォーテーション)」または「’(シングルクォーテーション)」です。

//p

で、すべてのp要素を表し、

//p[@class="red"]

で、すべてのp要素の内、class属性が「red」であるものを表します。

id属性

class要素はスタイルシートを指定するために用いるため、必ずしも一意に要素を特定できるわけではありません。
一方、id属性は、HTML文書内で一意に定めることが約束されています(※1)。よってid要素を使用すれば要素を一意に特定することができます。

//div[@id="main_container"]/p[@class="red"]

のように記述すれば、div要素までは特定できるので、他のdiv要素内に、class属性がredのp要素があっても、気にする必要はありません。

※1:id属性が重複しないのは、HTMLの規約上の定めであって、ブラウザで保証されているわけではありません。もし重複したid属性を持つページであっても、エラーにならずにブラウザで表示されます。

WinGoferのXPath取得ツールは、重複チェックを行っているため、もしidが重複する場合でも、要素を一意に特定できるXPathを取得することができます。

XPathの書き方

WinGofrで使用できるXPathの記述例
XPath内容
/htmlhtmlルート
//*すべての要素
//divすべてのdiv要素
//div[1]すべてのdiv要素の中で1番目のもの
//div[last()]すべてのdiv要素の中で最後のもの
//div[1]/p[2]1番目のdiv要素の直下にあるp要素の中で2番目のもの
//div[1]//p[2]1番目のdiv要素内にあるp要素の中で2番目のもの(子孫要素)
//*[@id="id1″]id属性が「id1」の要素
//div[@id="id1″]id属性が「id1」のdiv要素
//input[@type="text"][@value="テキスト"]type属性が「text」でvalue属性「テキスト」のinput要素
//p[a[contains(@href,"htttps://xxxxx")]]p要素の内、href属性が「htttps://xxxxx」を含むa要素を持つもの
//span[@class=’class1′]class属性が「class1」のすべてのspan要素
//span[@class=’class1 class2′]class属性が「class1,class2」のすべてのspan要素
//span[contains(@class,’class1 class2′)]「class1」と「class2」をclass属性に持つすべてのspan要素(他にclassがあってもOK)
//span[@hoge=’hoge’]hoge属性「hoge」を持つすべてのspan要素
//p[@text()="テキスト1″]text(innerText)が「テキスト1」のp要素(完全一致)
//p[contains(text(),"テキスト1")]textが「テキスト1」を含むp要素(部分一致)
//p[starts-with(text(),"テキスト1")]先頭のtextが「テキスト1」のp要素(※2)
//input[@type="radio"][1]/following-sibling::label[1]1番目のradioボタンと同じ階層かつ、radioより後ろにあるlabel要素の内、1番目のもの(自分より後の兄弟要素)
//label[@for="radio1″]/preceding-sibling::input[1]for属性が「radio1」のlabel要素と、同一階層かつlabelより前にあるinput要素の内、1番目のもの(自分より前の兄弟要素)

※2:ends-withは使用できません。

演算子
記号説明記入例内容
..親要素//input[@id="id1″]/../p[1]id属性「id1」を持つinput要素の親要素の直下で、最初のp要素(兄弟要素)
and論理積
(かつ)
//*[@name="name1″ and @class="class1″]name属性が「name1」かつ、class属性が「class1」の全ての要素
or論理和
(または)
//*[@name="name1″ or @class="class1″][1]name属性が「name1」またはclass属性が「class1」の要素の内、1番目のもの
not否定
(でない)
//table[@id="id1″]//td[not(contains(@class,"class1″))]id属性「id1」を持つテーブル要素内にあるtd要素で、class属性に「class1」を含まないもの

XPath