PHPのXPath関数を使用する場合、多くの開発者はさまざまなエラー、特にXPath構文関連の問題に遭遇します。 XPathは、XMLドキュメント内のデータを見つけるために使用される言語です。 PHPと組み合わせて使用すると、強力なクエリ機能はデータ抽出のプロセスを大幅に簡素化できます。ただし、その構文と使用法の詳細により、多くの場合、いくつかのエラーとトラブルにつながります。この記事では、PHPのXPath関数をより適切に使用するのに役立つ一般的なXPathエラーとそのソリューションを共有します。
最も一般的な間違いの1つは、XMLを処理するときにXMLファイルが正しくロードされないことです。この問題により、 XPath関数がXMLドキュメントを正しく解析できないため、エラーまたは空の結果が返されます。
エラー例:
<span><span><span class="hljs-variable">$xml</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title class_">DOMDocument</span></span><span>();
</span><span><span class="hljs-variable">$xml</span></span><span>-></span><span><span class="hljs-title function_ invoke__">load</span></span><span>(</span><span><span class="hljs-string">'invalid.xml'</span></span><span>); </span><span><span class="hljs-comment">// 読み取り失敗XML書類</span></span><span>
</span><span><span class="hljs-variable">$xpath</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title class_">DOMXPath</span></span><span>(</span><span><span class="hljs-variable">$xml</span></span><span>);
</span><span><span class="hljs-variable">$result</span></span><span> = </span><span><span class="hljs-variable">$xpath</span></span><span>-></span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">'//book'</span></span><span>);
</span></span>
解決:
まず、XMLファイルへのパスが正しいこと、およびXMLファイル自体が有効であることを確認してください。 XMLファイルが正しくロードされているかどうかを確認できます。
<span><span><span class="hljs-variable">$xml</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title class_">DOMDocument</span></span><span>();
</span><span><span class="hljs-keyword">if</span></span><span> (!</span><span><span class="hljs-variable">$xml</span></span><span>-></span><span><span class="hljs-title function_ invoke__">load</span></span><span>(</span><span><span class="hljs-string">'valid.xml'</span></span><span>)) {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">'XML書類加载失败'</span></span><span>;
</span><span><span class="hljs-keyword">exit</span></span><span>;
}
</span><span><span class="hljs-variable">$xpath</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title class_">DOMXPath</span></span><span>(</span><span><span class="hljs-variable">$xml</span></span><span>);
</span><span><span class="hljs-variable">$result</span></span><span> = </span><span><span class="hljs-variable">$xpath</span></span><span>-></span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">'//book'</span></span><span>);
</span></span>
Xpath構文自体も比較的厳格であり、少し不注意がエラーにつながります。 XPath式に構文エラーがある場合、 Query()メソッドはFALSEを返し、期待される結果が生成されません。
エラー例:
<span><span><span class="hljs-variable">$xpath</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title class_">DOMXPath</span></span><span>(</span><span><span class="hljs-variable">$xml</span></span><span>);
</span><span><span class="hljs-variable">$result</span></span><span> = </span><span><span class="hljs-variable">$xpath</span></span><span>-></span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">'book[@category="PHP"'</span></span><span>); </span><span><span class="hljs-comment">// ブラケットは閉じられていません</span></span><span>
</span></span>
解決:
Xpath式をチェックして、ブラケット、引用符、スラッシュ、その他のシンボルなどのシンボルが正しくペアになっていることを確認してください。例えば:
<span><span><span class="hljs-variable">$result</span></span><span> = </span><span><span class="hljs-variable">$xpath</span></span><span>-></span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">'//book[@category="PHP"]'</span></span><span>);
</span></span>
XMLを操作する場合、XMLドキュメントで名前空間が使用されている場合、 XPathクエリが故障しない場合があります。デフォルトではXPathは名前空間を考慮していないためです。
エラー例:
<span><span><span class="hljs-variable">$xml</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title class_">DOMDocument</span></span><span>();
</span><span><span class="hljs-variable">$xml</span></span><span>-></span><span><span class="hljs-title function_ invoke__">loadXML</span></span><span>(</span><span><span class="hljs-string">'<root xmlns:ns="http://example.com"><ns:book>Title</ns:book></root>'</span></span><span>);
</span><span><span class="hljs-variable">$xpath</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title class_">DOMXPath</span></span><span>(</span><span><span class="hljs-variable">$xml</span></span><span>);
</span><span><span class="hljs-variable">$result</span></span><span> = </span><span><span class="hljs-variable">$xpath</span></span><span>-></span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">'//ns:book'</span></span><span>);
</span></span>
解決:
DomxPathをインスタンス化するときは、 RegisterNamesPaceメソッドを使用して名前空間を登録して、名前空間の問題を解決できます。
<span><span><span class="hljs-variable">$xml</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title class_">DOMDocument</span></span><span>();
</span><span><span class="hljs-variable">$xml</span></span><span>-></span><span><span class="hljs-title function_ invoke__">loadXML</span></span><span>(</span><span><span class="hljs-string">'<root xmlns:ns="http://example.com"><ns:book>Title</ns:book></root>'</span></span><span>);
</span><span><span class="hljs-variable">$xpath</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title class_">DOMXPath</span></span><span>(</span><span><span class="hljs-variable">$xml</span></span><span>);
</span><span><span class="hljs-variable">$xpath</span></span><span>-></span><span><span class="hljs-title function_ invoke__">registerNamespace</span></span><span>(</span><span><span class="hljs-string">'ns'</span></span><span>, </span><span><span class="hljs-string">'http://example.com'</span></span><span>);
</span><span><span class="hljs-variable">$result</span></span><span> = </span><span><span class="hljs-variable">$xpath</span></span><span>-></span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">'//ns:book'</span></span><span>);
</span></span>
xpath-> query()メソッドは、 domnodelistオブジェクトを返します。クエリが成功したとしても、結果が空になり、結果の判断を下す必要があります。
エラー例:
<span><span><span class="hljs-variable">$xpath</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title class_">DOMXPath</span></span><span>(</span><span><span class="hljs-variable">$xml</span></span><span>);
</span><span><span class="hljs-variable">$result</span></span><span> = </span><span><span class="hljs-variable">$xpath</span></span><span>-></span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">'//book'</span></span><span>);
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-variable">$result</span></span><span>-></span><span><span class="hljs-title function_ invoke__">item</span></span><span>(</span><span><span class="hljs-number">0</span></span><span>)->nodeValue; </span><span><span class="hljs-comment">// ノードが見つからないため、エラーが報告される場合があります</span></span><span>
</span></span>
解決:
クエリの結果にアクセスする前に、それらが存在することを確認してください。
<span><span><span class="hljs-variable">$xpath</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title class_">DOMXPath</span></span><span>(</span><span><span class="hljs-variable">$xml</span></span><span>);
</span><span><span class="hljs-variable">$result</span></span><span> = </span><span><span class="hljs-variable">$xpath</span></span><span>-></span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">'//book'</span></span><span>);
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$result</span></span><span>->length > </span><span><span class="hljs-number">0</span></span><span>) {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-variable">$result</span></span><span>-></span><span><span class="hljs-title function_ invoke__">item</span></span><span>(</span><span><span class="hljs-number">0</span></span><span>)->nodeValue;
} </span><span><span class="hljs-keyword">else</span></span><span> {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">'一致するノードは見つかりませんでした'</span></span><span>;
}
</span></span>
domnodelistオブジェクトはオブジェクトの配列であるため、ノードにアクセスするときに正しいインデックスが必要です。よくある間違いは、境界のないインデックスの長さまたは結果がチェックされないことです。
エラー例:
<span><span><span class="hljs-variable">$xpath</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title class_">DOMXPath</span></span><span>(</span><span><span class="hljs-variable">$xml</span></span><span>);
</span><span><span class="hljs-variable">$result</span></span><span> = </span><span><span class="hljs-variable">$xpath</span></span><span>-></span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">'//book'</span></span><span>);
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-variable">$result</span></span><span>-></span><span><span class="hljs-title function_ invoke__">item</span></span><span>(</span><span><span class="hljs-number">10</span></span><span>)->nodeValue; </span><span><span class="hljs-comment">// クエリの結果がより少ない場合101つのノード,コードはエラーを報告します</span></span><span>
</span></span>
解決:
domnodelistオブジェクトの長さを確認して、インデックスが有効な範囲内にあることを確認します。
<span><span><span class="hljs-variable">$xpath</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title class_">DOMXPath</span></span><span>(</span><span><span class="hljs-variable">$xml</span></span><span>);
</span><span><span class="hljs-variable">$result</span></span><span> = </span><span><span class="hljs-variable">$xpath</span></span><span>-></span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">'//book'</span></span><span>);
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$result</span></span><span>->length > </span><span><span class="hljs-number">10</span></span><span>) {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-variable">$result</span></span><span>-></span><span><span class="hljs-title function_ invoke__">item</span></span><span>(</span><span><span class="hljs-number">10</span></span><span>)->nodeValue;
} </span><span><span class="hljs-keyword">else</span></span><span> {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">'十分なノードがありません'</span></span><span>;
}
</span></span>
XPath式が複雑すぎる場合、特に複数の条件または複雑なロジックを含む場合、 XPathはエラーを報告したり、誤った結果を返したりする場合があります。この場合、クエリまたはステップバイステップのデバッグを簡素化することができます。
エラー例:
<span><span><span class="hljs-variable">$xpath</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title class_">DOMXPath</span></span><span>(</span><span><span class="hljs-variable">$xml</span></span><span>);
</span><span><span class="hljs-variable">$result</span></span><span> = </span><span><span class="hljs-variable">$xpath</span></span><span>-></span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">'//book[@category="PHP" and @author="John"]'</span></span><span>);
</span></span>
解決:
Xpathの式を簡素化し、徐々に条件を追加し、それらをデバッグして、各条件が有効であることを確認してください。
<span><span><span class="hljs-variable">$result</span></span><span> = </span><span><span class="hljs-variable">$xpath</span></span><span>-></span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">'//book[@category="PHP"]'</span></span><span>); </span><span><span class="hljs-comment">// 最初に単一の条件を確認します</span></span><span>
</span><span><span class="hljs-variable">$result</span></span><span> = </span><span><span class="hljs-variable">$xpath</span></span><span>-></span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">'//book[@category="PHP" and @author="John"]'</span></span><span>); </span><span><span class="hljs-comment">// 2番目の条件を追加します</span></span><span>
</span></span>
domnodelistは配列オブジェクトですが、配列と正確に等しいものではありません。場合によっては、配列のように直接アクセスまたは処理することはできない場合があります。この問題を解決するために、最初にドムノデリストを配列に変換できます。
エラー例:
<span><span><span class="hljs-variable">$xpath</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title class_">DOMXPath</span></span><span>(</span><span><span class="hljs-variable">$xml</span></span><span>);
</span><span><span class="hljs-variable">$result</span></span><span> = </span><span><span class="hljs-variable">$xpath</span></span><span>-></span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">'//book'</span></span><span>);
</span><span><span class="hljs-keyword">foreach</span></span><span> (</span><span><span class="hljs-variable">$result</span></span><span> </span><span><span class="hljs-keyword">as</span></span><span> </span><span><span class="hljs-variable">$node</span></span><span>) {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-variable">$node</span></span><span>->nodeValue; </span><span><span class="hljs-comment">// これにより、エラーが発生します</span></span><span>
}
</span></span>
解決:
domnodelistを配列に変換してループします。
<span><span><span class="hljs-variable">$xpath</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title class_">DOMXPath</span></span><span>(</span><span><span class="hljs-variable">$xml</span></span><span>);
</span><span><span class="hljs-variable">$result</span></span><span> = </span><span><span class="hljs-variable">$xpath</span></span><span>-></span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">'//book'</span></span><span>);
</span><span><span class="hljs-variable">$nodes</span></span><span> = </span><span><span class="hljs-title function_ invoke__">iterator_to_array</span></span><span>(</span><span><span class="hljs-variable">$result</span></span><span>); </span><span><span class="hljs-comment">// 配列に変換します</span></span><span>
</span><span><span class="hljs-keyword">foreach</span></span><span> (</span><span><span class="hljs-variable">$nodes</span></span><span> </span><span><span class="hljs-keyword">as</span></span><span> </span><span><span class="hljs-variable">$node</span></span><span>) {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-variable">$node</span></span><span>->nodeValue;
}
</span></span>