【PHP8.x】DOMXPath::query()メソッドの使い方
queryメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
『queryメソッドは、指定されたXPath式を評価し、マッチしたノードを返す処理を実行するメソッドです。』
このメソッドは、DOMドキュメントに対してXPathクエリを実行するために使用されます。XPathとは、XMLやHTMLドキュメント内の特定の要素、属性、テキストなどを指定するための強力なクエリ言語です。第1引数に、検索したい条件をXPath式として文字列で渡します。例えば、//pという式はドキュメント内の全てのp要素を選択します。オプションの第2引数にDOMNodeオブジェクトを渡すと、検索範囲をそのノード以下に限定することができます。この引数を省略した場合は、ドキュメント全体が検索対象となります。メソッドが成功すると、結果は主にDOMNodeListオブジェクトとして返されます。このオブジェクトには、XPath式にマッチした全てのノードが含まれています。ただし、XPath式が数値や文字列、真偽値を評価するように書かれている場合は、その型の値が直接返されることもあります。式が無効であったり、何らかのエラーが発生した場合にはfalseを返します。このメソッドにより、複雑な構造を持つドキュメントからでも、目的の情報を効率的に抽出することが可能になります。
構文(syntax)
1DOMXPath::query(string $expression, ?DOMNode $contextNode = null, bool $registerNodeNS = true): DOMNodeList|false
引数(parameters)
string $expression, ?DOMNode $contextNode = null, bool $registerNodeNS = true
- string $expression: XPathクエリ文字列
- ?DOMNode $contextNode = null: XPathクエリの評価対象となるDOMNode。指定しない場合はドキュメント全体が対象
- bool $registerNodeNS = true: XML名前空間を自動的に登録するかどうかを示すブール値
戻り値(return)
DOMNodeList|false
DOMXPath::query メソッドは、XPathクエリを実行し、マッチしたノードのリストをDOMNodeListオブジェクトとして返します。クエリが失敗した場合は false を返します。
サンプルコード
PHP DOMXPath::queryで要素を検索する
1<?php 2 3/** 4 * 指定されたHTMLコンテンツから、DOMXPath::queryを使用して特定の要素を検索し、 5 * そのテキスト内容を出力するサンプル関数です。 6 * 7 * @return void 8 */ 9function findElementsWithXPathQuery(): void 10{ 11 // 解析対象のサンプルHTML文字列 12 $html = <<<HTML 13<!DOCTYPE html> 14<html lang="ja"> 15<head> 16 <title>DOMXPath::query のサンプル</title> 17</head> 18<body> 19 <h1>プログラミング言語リスト</h1> 20 <div id="main-contents"> 21 <p class="description">人気のプログラミング言語です。</p> 22 <ul> 23 <li class="language">PHP</li> 24 <li class="language">JavaScript</li> 25 <li class="language static">Go</li> 26 </ul> 27 </div> 28 <div id="sub-contents"> 29 <p class="description">その他の言語。</p> 30 <ul> 31 <li class="language">C++</li> 32 </ul> 33 </div> 34</body> 35</html> 36HTML; 37 38 // DOMDocumentオブジェクトを生成し、HTMLを読み込む 39 $dom = new DOMDocument(); 40 // HTML5のタグを正しく解釈するため、libxmlのエラーを内部で処理するように設定 41 libxml_use_internal_errors(true); 42 $dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); 43 libxml_clear_errors(); 44 45 // DOMDocumentからDOMXPathオブジェクトを生成 46 $xpath = new DOMXPath($dom); 47 48 // XPath式を定義: idが 'main-contents' のdiv要素内にある、 49 // classが 'language' のli要素をすべて選択する 50 $expression = "//div[@id='main-contents']//li[@class='language']"; 51 52 // queryメソッドを実行して、XPath式に一致するノードを取得 53 // 戻り値は DOMNodeList オブジェクト、または式が不正な場合は false 54 $nodes = $xpath->query($expression); 55 56 // 取得したノードリスト(DOMNodeList)をループ処理 57 if ($nodes instanceof DOMNodeList) { 58 echo "id='main-contents' 内の class='language' を持つ要素:" . PHP_EOL; 59 foreach ($nodes as $node) { 60 // 各ノード(DOMElement)のテキスト内容(nodeValue)を出力 61 echo "- " . $node->nodeValue . PHP_EOL; 62 } 63 } else { 64 echo "要素の検索に失敗しました。" . PHP_EOL; 65 } 66} 67 68// サンプル関数を実行 69findElementsWithXPathQuery();
PHPのDOMXPath::queryメソッドは、HTMLやXMLドキュメントの中から、指定した条件に一致する要素(ノード)を検索するためのものです。このメソッドは、検索条件を記述したXPath式を第一引数に受け取ります。
サンプルコードでは、まず文字列のHTMLをDOMDocumentオブジェクトに読み込ませ、そこからXPathを扱うためのDOMXPathオブジェクトを生成しています。次に、//div[@id='main-contents']//li[@class='language']というXPath式を定義します。これは「idが'main-contents'のdiv要素内にある、classが'language'のli要素をすべて選択する」という検索条件を意味します。
$xpath->query()でこの式を実行すると、条件に一致した要素がDOMNodeListオブジェクトとして返されます。これは見つかった要素のリストと考えることができます。もしXPath式が文法的に間違っているなど、検索に失敗した場合はfalseが返ります。コードでは、返ってきた値がDOMNodeListであることを確認した上でforeachを使い、リスト内の各要素からテキスト内容(nodeValue)を取り出して出力しています。これにより、指定した条件に合う「PHP」と「JavaScript」という文字列が表示されます。
DOMXPath::queryメソッドは、XPath式が不正な場合にfalseを返すため、必ず戻り値がDOMNodeListオブジェクトであるかを確認してから処理を行う必要があります。サンプルコードのようにinstanceofでチェックすると安全です。また、XPath式は厳密に解釈されます。例えば@class='language'という指定は、クラス名が完全に一致する要素のみを選択し、class="language static"のように他のクラスが含まれる要素は対象外となる点に注意が必要です。外部のHTMLを扱う際は、予期せぬ構成や文字エンコーディングの違いでエラーや文字化けが発生する可能性があるため、libxmlによるエラー抑制や、事前のエンコーディング確認が重要になります。
PHP DOMXPath queryでXMLを検索する
1<?php 2 3/** 4 * XML文字列からXPathクエリ文字列を使用して書籍のタイトルを検索します。 5 * 6 * DOMXPath::query() メソッドは、XMLドキュメントに対して 7 * XPath 式 (クエリ文字列) を実行し、結果を DOMNodeList として返します。 8 * 9 * @return void 10 */ 11function findBookTitlesByQueryString(): void 12{ 13 // サンプルとなるXMLデータ 14 $xmlString = <<<XML 15<?xml version="1.0" encoding="UTF-8"?> 16<books> 17 <book category="cooking"> 18 <title lang="en">Everyday Italian</title> 19 <author>Giada De Laurentiis</author> 20 </book> 21 <book category="children"> 22 <title lang="en">Harry Potter</title> 23 <author>J. K. Rowling</author> 24 </book> 25 <book category="web"> 26 <title lang="en">Learning XML</title> 27 <author>Erik T. Ray</author> 28 </book> 29</books> 30XML; 31 32 // DOMDocumentオブジェクトを作成し、XMLを読み込む 33 $dom = new DOMDocument(); 34 $dom->loadXML($xmlString); 35 36 // DOMXPathオブジェクトをDOMDocumentから作成 37 $xpath = new DOMXPath($dom); 38 39 // 検索するためのXPathクエリ文字列を定義 40 // ここでは 'web' カテゴリに属する book 要素の title 要素をすべて選択 41 $queryString = "//book[@category='web']/title"; 42 43 // query() メソッドを実行してノードリストを取得 44 $nodeList = $xpath->query($queryString); 45 46 // query() が結果を返したか確認 47 if ($nodeList instanceof DOMNodeList) { 48 echo "クエリ '{$queryString}' に一致した書籍タイトル:" . PHP_EOL; 49 50 // 見つかったノードをループ処理して内容を表示 51 foreach ($nodeList as $node) { 52 // $node->nodeValue は要素のテキスト内容を取得するプロパティ 53 echo "- " . $node->nodeValue . PHP_EOL; 54 } 55 } else { 56 echo "クエリの実行に失敗しました。" . PHP_EOL; 57 } 58} 59 60// 作成した関数を実行 61findBookTitlesByQueryString(); 62 63?>
このサンプルコードは、PHPのDOMXPath::query()メソッドを使用して、XMLデータの中からXPathクエリ文字列に一致する要素を検索する方法を示しています。このメソッドは、XMLドキュメント構造を解析し、指定した条件に合う要素群を取得するために利用されます。
コードでは、まずDOMDocumentオブジェクトにXMLデータを読み込ませ、それを基にDOMXPathオブジェクトを生成します。次に、$queryString変数に//book[@category='web']/titleというXPathクエリ文字列を定義しています。これは「ドキュメント内のどこにあっても、category属性が'web'であるbook要素の子要素であるtitle要素」という検索条件を意味します。
$xpath->query()の第一引数$expressionには、この検索条件であるクエリ文字列を渡します。第二引数の$contextNodeを省略すると、ドキュメント全体が検索対象になります。
メソッドの実行が成功すると、条件に一致した要素(ノード)を格納したDOMNodeListオブジェクトが戻り値として返されます。サンプルではforeachでこのリストをループ処理し、各要素のテキスト内容をnodeValueプロパティで取得して表示しています。クエリ文字列が不正な場合など、実行に失敗した際にはfalseが返されるため、if文で戻り値がDOMNodeListであるかを確認してから処理を行っています。
DOMXPath::queryメソッドに渡すクエリ文字列は「XPath」という専用の記述ルールに従う必要があります。この構文を間違えると、意図した要素を取得できなかったり、処理が失敗したりする原因になります。メソッドの戻り値は、成功すればDOMNodeListオブジェクト、XPathの式が不正な場合はfalseです。そのため、戻り値がfalseでないことを必ず確認してから結果を利用するのが安全です。検索に一致する要素が0件だった場合はfalseではなく、空のDOMNodeListが返される点にも注意しましょう。実際のXMLでは「名前空間」が使われていることが多く、その場合は事前にregisterNamespaceメソッドを呼び出さないと要素を正しく選択できません。