【PHP8.x】Dom\XPath::evaluate()メソッドの使い方
evaluateメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
『evaluateメソッドは、指定されたXPath式を現在のコンテキストで評価し、その結果を返す処理を実行するメソッドです。主にXMLやHTMLドキュメントを解析したDOMオブジェクトの中から、特定の条件に合致するノード(要素、属性、テキストなど)を効率的に検索・取得するために使用されます。第一引数には、評価したいXPath式を文字列で指定します。第二引数には、オプションで検索の起点となるコンテキストノードを指定することができ、これを省略した場合はドキュメント全体が検索対象となります。このメソッドの大きな特徴は、評価するXPath式の内容に応じて、返り値の型が動的に変わる点です。例えば、複数の要素を選択する式であればDOMNodeListオブジェクトが、count()のような関数を使えば数値が、要素のテキスト内容を取得すれば文字列が返されます。これにより、単にノードを検索するだけでなく、ドキュメントに関する多様な情報を柔軟に取得できます。もし指定した式が無効な場合はfalseを返します。
構文(syntax)
1$document = new DOMDocument(); 2$document->loadXML('<data><item>value1</item><item>value2</item></data>'); 3 4$xpath = new Dom\XPath($document); 5 6$expression = '/data/item'; 7$contextNode = $document->documentElement; 8 9$result = $xpath->evaluate($expression, $contextNode, registerNodeNS: false);
引数(parameters)
string $expression, ?Dom\Node $contextNode = null, bool $registerNodeNS = true
- string $expression: XPathクエリ文字列
- ?Dom\Node $contextNode: XPathクエリのコンテキストとなるDOMノード。指定しない場合はドキュメント全体が対象。
- bool $registerNodeNS = true: XPathクエリ内で使用される名前空間を自動的に登録するかどうか。
戻り値(return)
Dom\NodeList|string|float|bool|null
XPathクエリを実行した結果、ノードのリスト、文字列、浮動小数点数、真偽値、あるいは null が返されます。
サンプルコード
PHP Dom\XPath evaluate でXML情報抽出
1<?php 2 3declare(strict_types=1); 4 5/** 6 * Dom\XPath::evaluate を使用してXMLデータから情報を抽出するサンプル関数。 7 * 8 * この関数は、XMLドキュメントを読み込み、XPath式を使って 9 * 1. 特定の要素のリスト(ノードリスト) 10 * 2. 特定の要素のテキスト内容(文字列) 11 * 3. 要素の数(数値) 12 * を取得する方法を示します。 13 */ 14function evaluateXPathExpressionExample(): void 15{ 16 // サンプルとして使用するXMLデータ 17 $xmlString = <<<XML 18<?xml version="1.0" encoding="UTF-8"?> 19<books> 20 <book category="web"> 21 <title lang="en">Learning XML</title> 22 <author>Erik T. Ray</author> 23 </book> 24 <book category="children"> 25 <title lang="en">Harry Potter</title> 26 <author>J. K. Rowling</author> 27 </book> 28</books> 29XML; 30 31 // 1. DOMDocumentオブジェクトを準備し、XMLを読み込む 32 $dom = new Dom\Document(); 33 $dom->loadXML($xmlString); 34 35 // 2. DOMXPathオブジェクトをDOMDocumentから作成する 36 $xpath = new Dom\XPath($dom); 37 38 // 3. XPath式を評価(evaluate)して結果を取得する 39 // 例1: ノードリストを取得する 40 // -> category属性が "web" であるすべてのbook要素のtitle要素を取得 41 $expressionForNodeList = '//book[@category="web"]/title'; 42 $titles = $xpath->evaluate($expressionForNodeList); 43 44 // 取得したノードリスト(Dom\NodeList)から各要素の値を取り出して表示 45 echo "■ 'web' カテゴリの書籍タイトル:" . PHP_EOL; 46 if ($titles instanceof Dom\NodeList) { 47 foreach ($titles as $title) { 48 echo $title->nodeValue . PHP_EOL; // "Learning XML" が出力される 49 } 50 } 51 echo PHP_EOL; 52 53 // 例2: 文字列値を取得する 54 // -> 'Harry Potter' というタイトルの著者名を取得 55 $expressionForString = 'string(//book[title="Harry Potter"]/author)'; 56 $author = $xpath->evaluate($expressionForString); 57 58 echo "■ 'Harry Potter' の著者名:" . PHP_EOL; 59 if (is_string($author)) { 60 echo $author . PHP_EOL; // "J. K. Rowling" が出力される 61 } 62 echo PHP_EOL; 63 64 // 例3: 数値を取得する 65 // -> すべてのbook要素の数をカウント 66 $expressionForNumber = 'count(//book)'; 67 $bookCount = $xpath->evaluate($expressionForNumber); 68 69 echo "■ 書籍の総数:" . PHP_EOL; 70 if (is_float($bookCount)) { 71 echo $bookCount . " 冊" . PHP_EOL; // "2 冊" が出力される 72 } 73} 74 75// 作成した関数を実行 76evaluateXPathExpressionExample();
Dom\XPath::evaluateメソッドは、XMLドキュメントに対して「XPath式」という一種の検索ルールを実行し、目的の情報を抽出するための関数です。
第一引数$expressionには、どの要素を探すか、または何を計算するかを文字列で指定します。これがこのメソッドの核となる部分です。第二引数$contextNodeは検索の開始位置を指定するもので、省略するとXMLドキュメント全体が対象となります。
このメソッドの最大の特徴は、第一引数に指定したXPath式の内容によって、戻り値の型が変化することです。サンプルコードでは3つの例が示されています。まず、特定の条件に合う複数のXML要素を取得する場合、戻り値はDom\NodeListという要素のリストになります。次に、XPathのstring()関数を使って特定要素のテキスト情報だけを抜き出すと、戻り値はstring型の文字列となります。さらに、count()関数で要素の個数を数えると、戻り値はfloat型の数値になります。
このように、evaluateメソッドは1つの関数でありながら、XPath式の書き方次第で、要素の集合、特定の文字列、数値など、様々な形式で結果を柔軟に受け取ることができるため、XMLデータの操作において非常に強力です。
evaluateメソッドは、実行するXPath式によって戻り値の型が Dom\NodeList、string、float などに変わるのが最大の特徴です。そのため、サンプルコードのように instanceof や is_string() といった関数を用いて、必ず受け取った値の型をチェックしてから処理することが重要です。この型チェックを怠ると、予期せぬエラーの原因となります。また、XPath式で string() や count() などの関数を使うと、取得したい情報の型を明示的に指定できます。実際のXMLでは名前空間が使われることも多く、その場合は registerNamespace() での事前登録が必要になる点も覚えておきましょう。
PHP XPathで文字列数式を評価する
1<?php 2 3declare(strict_types=1); 4 5/** 6 * Dom\XPath::evaluate を使用して、文字列で表現された数式を計算します。 7 * 8 * XPath 式はノードを検索するだけでなく、四則演算などの数値計算もサポートしています。 9 * この機能を利用して、PHPのコードとして直接実行することなく、安全に文字列の数式を評価します。 10 * 11 * @param string $expression 計算したい数式(例: '2 * (3 + 4)') 12 * @return float|null 計算結果の数値。式が無効な場合は null を返します。 13 */ 14function evaluateMathExpression(string $expression): ?float 15{ 16 // Dom\XPath をインスタンス化するには、まず Dom\Document オブジェクトが必要です。 17 // 数式の計算が目的であるため、中身は空のドキュメントで問題ありません。 18 $dom = new Dom\Document(); 19 $xpath = new Dom\XPath($dom); 20 21 // evaluate() メソッドは、第1引数に与えられた XPath 式を評価します。 22 // 数式が有効な XPath 式として解釈され、計算結果が float 型で返されます。 23 // 式が不正な場合、false が返されることがあります。 24 $result = @$xpath->evaluate($expression); 25 26 if ($result === false) { 27 return null; 28 } 29 30 return (float)$result; 31} 32 33// --- 実行例 --- 34 35// 計算したい数式を文字列として定義します。 36$mathString = '10 + (5 * 8) / 4 - 2.5'; // 10 + 40 / 4 - 2.5 = 10 + 10 - 2.5 = 17.5 37 38// 関数を呼び出して計算を実行します。 39$answer = evaluateMathExpression($mathString); 40 41if ($answer !== null) { 42 echo '計算式: ' . $mathString . PHP_EOL; 43 echo '結果: ' . $answer . PHP_EOL; 44} else { 45 echo '無効な計算式です: ' . $mathString . PHP_EOL; 46} 47 48?>
このサンプルコードは、PHPのDom\XPathクラスが持つevaluateメソッドを利用して、文字列で記述された数式を安全に計算する方法を示しています。Dom\XPathは、本来XMLドキュメントから情報を検索するための機能ですが、その際に用いるXPath式は、四則演算などの数値計算もサポートしています。
evaluateメソッドは、第1引数 $expression に評価したいXPath式を文字列として受け取ります。このサンプルでは、その引数に '10 + (5 * 8) / 4 - 2.5' のような計算式を渡しています。メソッドは渡された式を解釈・計算し、その結果を返します。
数式が正しく評価された場合、戻り値は計算結果の数値(float型)になります。もし式に誤りがあるなど、評価に失敗した場合はfalseを返すことがあります。この性質を利用することで、PHPのコードとして直接実行するeval()関数などを使わずに、外部から与えられた文字列の数式を安全に評価できます。コード内のevaluateMathExpression関数は、この一連の処理をまとめた実用的な例です。
このコードはXML文書を操作するための Dom\XPath クラスを応用し、安全に数式文字列を計算するものです。PHPの eval() 関数と異なり、任意のコードが実行される危険性がないため、ユーザーからの入力を扱う際に有効です。注意点として、数式計算が目的の場合でも、最初に Dom\Document のインスタンスを作成する必要があります。また、evaluate メソッドは不正な式が入力されると警告を発生させ false を返すことがあります。サンプルコードでは @ でこの警告を抑制し、戻り値を厳密に false と比較してエラーを判定しています。計算できるのは四則演算など、XPathがサポートする演算子や関数のみです。