【PHP8.x】DOMXPath::evaluate()メソッドの使い方
evaluateメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
『evaluateメソッドは、指定されたXPath式を現在のドキュメントコンテキストで評価し、その結果を取得するために実行するメソッドです。第一引数には、検索や計算のルールを定義したXPath式を文字列として渡します。XPath式を用いることで、XMLやHTMLドキュメントの中から特定のタグ名を持つ要素、特定の値を持つ属性、あるいは特定のテキスト内容を持つノードなどを柔軟に指定できます。第二引数には、オプションで式の評価を開始する基準点となるコンテキストノード(DOMNodeオブジェクト)を指定することが可能です。この引数を省略した場合は、ドキュメントのルート要素が基準点として使用されます。このメソッドが返す値の型は、実行したXPath式によって決まります。例えば、条件に一致するノードの集合(DOMNodeList)、数値の計算結果、文字列、あるいは真偽値(boolean)など、様々な型の結果が返されます。これにより、複雑なドキュメント構造から必要な情報を効率的かつ正確に抽出する強力な手段を提供します。
構文(syntax)
1$result = $xpath->evaluate( 2 string $expression, 3 ?DOMNode $contextNode = null, 4 bool $registerNodeNS = true 5);
引数(parameters)
string $expression, ?DOMNode $contextNode = null, bool $registerNodeNS = true
- string $expression: 評価するXPath式を指定する文字列
- ?DOMNode $contextNode = null: XPath式の評価を開始するコンテキストノード。省略した場合、DOMXPathオブジェクトのルートノードが使用されます。
- bool $registerNodeNS = true: XPath式内で名前空間が使用されている場合、DOMXPathオブジェクトに名前空間を登録するかどうかを指定するブール値
戻り値(return)
mixed
DOMXPath::evaluate メソッドは、XPath式を評価した結果を返します。XPath式が単一のノードを返す場合はそのノードオブジェクト、複数のノードを返す場合は DOMNodeList オブジェクト、値(文字列、数値、真偽値など)を返す場合は PHP の値として返されます。
サンプルコード
PHP DOMXPath evaluateでXMLを抽出する
1<?php 2 3declare(strict_types=1); 4 5/** 6 * DOMXPath::evaluate を使用してXMLデータから情報を抽出するサンプルです。 7 */ 8function queryXmlWithXPath(): void 9{ 10 // 解析対象となるXML文字列を用意します。 11 $xmlString = <<<XML 12 <?xml version="1.0" encoding="UTF-8"?> 13 <bookstore> 14 <book category="COOKING"> 15 <title lang="en">Everyday Italian</title> 16 <author>Giada De Laurentiis</author> 17 <price>30.00</price> 18 </book> 19 <book category="CHILDREN"> 20 <title lang="en">Harry Potter</title> 21 <author>J. K. Rowling</author> 22 <price>29.99</price> 23 </book> 24 <book category="WEB"> 25 <title lang="en">Learning XML</title> 26 <author>Erik T. Ray</author> 27 <price>39.95</price> 28 </book> 29 </bookstore> 30 XML; 31 32 // DOMDocumentオブジェクトを生成し、XMLを読み込みます。 33 $dom = new DOMDocument(); 34 $dom->loadXML($xmlString); 35 36 // DOMDocumentオブジェクトからDOMXPathオブジェクトを生成します。 37 // これがXPath式を評価(実行)するためのメインオブジェクトです。 38 $xpath = new DOMXPath($dom); 39 40 // --- 例1: ノードのリストを取得する --- 41 // XPath式を定義します。ここでは、すべての<book>要素の下にある<title>要素を選択します。 42 $expressionForTitles = '/bookstore/book/title'; 43 44 // evaluate()メソッドで式を実行します。 45 // この式の場合、結果はDOMNodeListオブジェクトとして返されます。 46 $titles = $xpath->evaluate($expressionForTitles); 47 48 echo "すべての書籍のタイトル:\n"; 49 // 取得したノードのリストをループ処理して、テキスト内容を表示します。 50 if ($titles instanceof DOMNodeList) { 51 foreach ($titles as $title) { 52 echo "- " . $title->nodeValue . "\n"; 53 } 54 } 55 56 echo "\n"; 57 58 // --- 例2: 条件に合う要素を検索し、その数を数える --- 59 // XPath式を定義します。ここでは、'category'属性が'WEB'である<book>要素の数を数えます。 60 // XPathのcount()関数は、結果を数値(float)で返します。 61 $expressionForCount = "count(/bookstore/book[@category='WEB'])"; 62 63 // evaluate()メソッドで式を実行します。 64 $bookCount = $xpath->evaluate($expressionForCount); 65 66 echo "カテゴリが'WEB'の書籍の数: " . $bookCount . "\n"; 67 68 echo "\n"; 69 70 // --- 例3: 条件に合う要素から特定の文字列値を取得する --- 71 // XPath式を定義します。ここでは、'Harry Potter'というタイトルの書籍の価格を取得します。 72 // XPathのstring()関数は、結果を文字列(string)で返します。 73 $expressionForPrice = "string(/bookstore/book[title='Harry Potter']/price)"; 74 75 // evaluate()メソッドで式を実行します。 76 $price = $xpath->evaluate($expressionForPrice); 77 78 echo "Harry Potterの価格: " . $price . "\n"; 79} 80 81// 関数を実行して結果を表示します。 82queryXmlWithXPath(); 83
このサンプルコードは、PHPのDOMXPath::evaluateメソッドを使い、XMLデータから必要な情報を抽出する方法を示しています。このメソッドは、指定されたXPath式を評価(実行)し、その結果を返します。
第1引数の$expressionには、XML文書内でデータを検索するためのルールを記述したXPath式を文字列で指定します。例えば、サンプルコードでは特定の要素のリストを取得する式や、要素の数を数える式などが使われています。第2引数の$contextNodeは検索の開始点を指定できますが、省略すると文書全体が対象となります。
evaluateメソッドの戻り値の型は、実行したXPath式によって異なります。サンプルコードのように、複数の要素を検索する式の場合はDOMNodeListオブジェクトが、count()のような集計関数の場合は数値(float型)が、string()関数を使った場合や単一の値を取得する際は文字列(string型)が返されます。このように、evaluateメソッドはXPath式を駆使することで、ノードの集合から個別の値まで、様々な形式で柔軟にXMLデータを取得できる強力な機能です。
DOMXPath::evaluateメソッドの最も重要な注意点は、戻り値の型が一定ではないことです。実行するXPath式によって、ノードのリスト(DOMNodeList)、数値(float)、文字列(string)など、様々な型の値が返されます。このため、メソッドの実行結果を扱う際には、サンプルコードのようにinstanceof演算子などで必ず型を確認してから処理を行うことが重要です。型チェックを怠ると、予期せぬエラーの原因となります。また、XPath式の内容が結果のデータ型を決定するため、どのような式がどの型の値を返すかを理解して記述する必要があります。
PHP DOMXPath evaluate で文字列数式を計算する
1<?php 2 3declare(strict_types=1); 4 5/** 6 * DOMXPath::evaluate を使用して、文字列として与えられた数式を安全に計算します。 7 * 8 * この方法はPHPの eval() よりも安全な代替手段となり得ます。 9 * XPath 1.0 の数値演算機能を利用しているため、四則演算や一部の数学関数が使用可能です。 10 * 11 * @param string $expression 計算したい数式。除算は '/' ではなく 'div' を使います。 12 * @return float|int|string|bool 評価結果。式が無効な場合は警告と共に false を返すことがあります。 13 */ 14function evaluateMathExpression(string $expression): float|int|string|bool 15{ 16 // DOMXPath を利用するために、空の DOMDocument インスタンスを生成します。 17 // 評価する式がXMLドキュメントに依存しないため、中身は空で問題ありません。 18 $dom = new DOMDocument(); 19 $xpath = new DOMXPath($dom); 20 21 // evaluate メソッドで数式を評価します。第2引数 (contextNode) を省略することで、 22 // XMLのコンテキストなしに式が評価されます。 23 return $xpath->evaluate($expression); 24} 25 26// --- 実行コード --- 27 28// 計算したい数式を文字列で定義します。 29// XPathの仕様では、除算は '/' ではなく 'div' を使用することに注意してください。 30$mathString = '(100 - 25) * 2 div 5 + 3'; 31 32// 関数を呼び出して数式を評価・計算します。 33$result = evaluateMathExpression($mathString); 34 35// 結果を出力します。 36echo "Expression: {$mathString}" . PHP_EOL; 37echo "Result: {$result}" . PHP_EOL; 38// 実行結果: 39// Expression: (100 - 25) * 2 div 5 + 3 40// Result: 33 41 42echo PHP_EOL; 43 44// XPathが提供する数学関数を利用した例 45$functionMathString = 'floor(9.8) + ceiling(2.1)'; 46$resultWithFunction = evaluateMathExpression($functionMathString); 47 48echo "Expression: {$functionMathString}" . PHP_EOL; 49echo "Result: {$resultWithFunction}" . PHP_EOL; 50// 実行結果: 51// Expression: floor(9.8) + ceiling(2.1) 52// Result: 12 53
DOMXPath::evaluateメソッドは、本来XMLドキュメントから特定の情報を探し出すためにXPath式を評価する機能です。このサンプルコードでは、その機能を応用して、文字列として与えられた数式を安全に計算しています。
メソッドの第1引数$expressionには、評価したい式を文字列で渡します。サンプルでは'(100 - 25) * 2 div 5 + 3'のような数式がこれにあたります。XPath 1.0の仕様に従うため、除算には/ではなくdivキーワードを使用する必要がある点に注意してください。第2引数$contextNodeを省略すると、XMLの特定ノードに依存せず式自体が評価されるため、純粋な数式計算が可能になります。
戻り値は評価結果によって型が変わりますが、数式の場合は計算結果が数値(整数または浮動小数点数)として返されます。この方法は、任意のPHPコードを実行できてしまうeval()関数とは異なり、許可された演算や関数しか実行できないため、外部からの入力を計算する際にも安全な代替手段となります。サンプルではfloor()のようなXPathの組み込み関数も利用できることを示しています。
このコードは文字列の数式を安全に計算する便利な方法です。特に注意すべき点は、除算の演算子に / ではなく div を使用する点です。これは一般的なプログラミング言語と異なるXPathの仕様です。この方法は、任意のPHPコードを実行してしまう eval() 関数よりも安全ですが、使用できる演算子や数学関数はXPathで定義されたもの(floor, sumなど)に限られます。PHPの全ての数学関数が使えるわけではない点に注意してください。また、不正な数式を渡すと警告が出て false が返ることがあるため、計算結果を利用する際は想定外の値を考慮するとより安全です。