【PHP8.x】Dom\Document::getElementsByTagNameNS()メソッドの使い方
getElementsByTagNameNSメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
getElementsByTagNameNSメソッドは、XMLやHTMLドキュメントから、指定された名前空間URIとタグ名(ローカル名)に一致するすべての要素(エレメント)を検索し、それらをまとめて取得するメソッドです。このメソッドは、Dom\Documentクラスに属しており、ドキュメント全体の中から特定の条件に合う要素を探し出す際に利用されます。
プログラミングにおいて、XMLなどのドキュメントには、同じタグ名であっても異なる意味を持つ要素が存在する場合があります。これを区別するために「名前空間(Namespace)」という仕組みが使われます。たとえば、<svg:rect>と<html:p>のように、プレフィックスによって所属する名前空間が異なり、それぞれのタグが異なる定義を持つことがあります。getElementsByTagNameNSメソッドでは、この名前空間URIを指定することで、より正確に目的の要素を特定することが可能です。
メソッドの引数として、一つ目に検索したい名前空間URIを渡します。もしすべての名前空間を対象としたい場合は、'*'(アスタリスク)を指定します。二つ目の引数には、検索したい要素のローカル名、つまりプレフィックスを含まないタグ名を指定します。こちらもすべてのローカル名を対象とする場合は'*'を指定できます。
このメソッドは、条件に合致する要素が見つかった場合、それらをDom\NodeListというオブジェクトの形で返します。Dom\NodeListは、見つかった要素のリストを効率的に扱うためのものです。もし一致する要素が見つからなかった場合でも、空のDom\NodeListオブジェクトが返されるため、常に安全に処理を進めることができます。XMLドキュメントの特定の構造を持つデータを抽出したい場合などに、このメソッドは非常に強力なツールとなります。
構文(syntax)
1<?php 2 3$xmlString = <<<XML 4<?xml version="1.0" encoding="UTF-8"?> 5<root xmlns="http://example.com/ns1" xmlns:book="http://example.com/ns/books"> 6 <book:title>PHP Programming</book:title> 7 <item>Generic Item</item> 8 <book:author>John Doe</book:author> 9</root> 10XML; 11 12$document = new Dom\Document(); 13$document->loadXML($xmlString); 14 15$nodeList = $document->getElementsByTagNameNS('http://example.com/ns/books', 'title'); 16 17?>
引数(parameters)
?string $namespace, string $localName
- ?string $namespace: 要素の名前空間を指定する文字列。
nullを指定すると、名前空間を使用しない要素を検索します。 - string $localName: 検索する要素のローカル名(名前空間プレフィックスを除いた名前)を指定する文字列。
戻り値(return)
Dom\NodeList
指定された名前空間(namespace)に属する、すべての要素ノードをDom\NodeListオブジェクトとして取得します。
サンプルコード
PHP: getElementsByTagNameNSで要素を検索する
1<?php 2 3/** 4 * 指定されたXML文字列から、特定名前空間とローカル名を持つ要素を検索し、その情報を表示します。 5 * 6 * @param string $xmlString 検索対象のXML文字列。 7 * @param string|null $namespace 検索する要素の名前空間URI。 8 * 名前空間を持たない要素やデフォルト名前空間の要素を検索する場合はnullを指定します。 9 * @param string $localName 検索する要素のローカル名(タグ名から名前空間接頭辞を除いた部分)。 10 */ 11function findElementsByNamespaceAndTagName(string $xmlString, ?string $namespace, string $localName): void 12{ 13 // Dom\Document オブジェクトを作成します。 14 $dom = new Dom\Document(); 15 16 // XML 文字列をロードします。 17 // loadXML() は成功すると true を、失敗すると false を返します。 18 if (!$dom->loadXML($xmlString)) { 19 echo "エラー: XMLのロードに失敗しました。\n"; 20 return; 21 } 22 23 // Dom\Document::getElementsByTagNameNS メソッドを使用して、 24 // 指定された名前空間URIとローカル名に一致するすべての要素を検索します。 25 // 戻り値は Dom\NodeList オブジェクトで、見つかった要素のリストを含みます。 26 $nodeList = $dom->getElementsByTagNameNS($namespace, $localName); 27 28 // 検索条件を表示します。 29 $namespaceDisplay = $namespace === null ? "[なし]" : "'{$namespace}'"; 30 echo "--- 名前空間: {$namespaceDisplay}, ローカル名: '{$localName}' の要素を検索 ---\n"; 31 32 // 見つかった要素の数を表示します。 33 echo "見つかった要素数: " . $nodeList->count() . " 件\n"; 34 35 // 見つかった各要素の情報をループして表示します。 36 foreach ($nodeList as $node) { 37 // NodeList の要素は Dom\Node のインスタンスですが、 38 // 要素の具体的なプロパティにアクセスするため Dom\Element にキャストできるか確認します。 39 if ($node instanceof Dom\Element) { 40 echo " - タグ名 (tagName): " . $node->tagName . "\n"; 41 echo " 名前空間URI (namespaceURI): " . ($node->namespaceURI ?: '[なし]') . "\n"; 42 echo " ローカル名 (localName): " . $node->localName . "\n"; 43 // テキストコンテンツは前後の空白(改行など)をtrimで除去して表示します。 44 echo " テキストコンテンツ: '" . trim($node->textContent) . "'\n"; 45 echo " 属性:\n"; 46 // 要素が持つ属性をすべて表示します。 47 if ($node->hasAttributes()) { 48 foreach ($node->attributes as $attr) { 49 echo " - {$attr->name}: '{$attr->value}'\n"; 50 } 51 } else { 52 echo " (なし)\n"; 53 } 54 } 55 } 56 echo "\n"; // 各検索結果の間に空行を挿入 57} 58 59// サンプルXML文字列を定義します。 60// 名前空間 'bk' と 'auth' を持つ要素を含んでいます。 61$xmlContent = <<<XML 62<?xml version="1.0" encoding="UTF-8"?> 63<library xmlns:bk="http://example.com/books" xmlns:auth="http://example.com/authors"> 64 <bk:book id="b1"> 65 <bk:title>PHP入門</bk:title> 66 <auth:name>田中 太郎</auth:name> 67 </bk:book> 68 <bk:book id="b2"> 69 <bk:title>PHP実践ガイド</bk:title> 70 <auth:name>山田 花子</auth:name> 71 </bk:book> 72 <magazine> 73 <title>技術マガジン</title> 74 </magazine> 75</library> 76XML; 77 78// 1. 名前空間 'http://example.com/books' とローカル名 'title' を持つ要素を検索 79findElementsByNamespaceAndTagName($xmlContent, "http://example.com/books", "title"); 80 81// 2. 名前空間 'http://example.com/authors' とローカル名 'name' を持つ要素を検索 82findElementsByNamespaceAndTagName($xmlContent, "http://example.com/authors", "name"); 83 84// 3. 名前空間を持たない(またはデフォルト名前空間の)ローカル名 'title' を持つ要素を検索 85// この場合、namespace 引数に null を指定します。 86findElementsByNamespaceAndTagName($xmlContent, null, "title"); 87 88// 4. 存在しない名前空間とローカル名を持つ要素を検索 (結果は0件になることを確認) 89findElementsByNamespaceAndTagName($xmlContent, "http://example.com/books", "publisher"); 90 91?>
PHP 8のDom\Document::getElementsByTagNameNSメソッドは、XML文書の中から、指定された名前空間URIとローカル名(タグ名)を持つすべての要素を検索するために利用されます。第一引数には検索対象の名前空間URIを文字列で指定し、名前空間を持たない要素やデフォルト名前空間の要素を検索したい場合はnullを指定します。第二引数には、タグ名から名前空間接頭辞を除いた「ローカル名」を文字列で指定します。このメソッドは、検索条件に一致するすべての要素をDom\NodeListオブジェクトとして返します。見つからなかった場合は空のリストが返されます。
サンプルコードでは、Dom\DocumentオブジェクトにXML文字列を読み込み、findElementsByNamespaceAndTagName関数を通じてgetElementsByTagNameNSメソッドの挙動を確認しています。具体的には、「http://example.com/books」名前空間の「title」要素や、名前空間を持たない「title」要素など、異なる条件で要素を検索しています。検索結果の`Dom\NodeList`は、`foreach`ループで個々の要素を取り出し、そのタグ名、名前空間URI、ローカル名、テキストコンテンツ、属性などを表示しています。これにより、XML文書から特定の要素群を効率的に抽出する仕組みを学ぶことができます。
このコードは、XMLドキュメントから指定された名前空間URIとローカル名を持つ要素を検索する方法を示しています。重要な点として、getElementsByTagNameNSメソッドの第一引数には名前空間の接頭辞ではなく、完全な名前空間URIを指定する必要があります。名前空間を持たない要素やデフォルト名前空間の要素を検索する場合は、この引数にnullを指定します。また、XML文字列をロードするDom\Document::loadXMLメソッドは、XMLが不正な場合に失敗することがありますので、必ず戻り値を確認し、エラー処理を記述するようにしてください。検索結果はDom\NodeListとして返され、ループで個々の要素にアクセスする際には、対象がDom\Elementのインスタンスであることを確認すると、安全に要素のプロパティを利用できます。
PHP DOM getElementsByTagNameNSによる要素検索
1<?php 2 3/** 4 * Dom\Document::getElementsByTagNameNS メソッドの使用例を示します。 5 * 特定の名前空間とローカル名を持つXML要素を検索し、その内容を表示します。 6 * システムエンジニアを目指す初心者の方にも分かりやすいように、コメントと例を記載しています。 7 */ 8function demonstrateGetElementsByTagNameNS(): void 9{ 10 // 1. Dom\Document クラスの新しいインスタンスを作成します。 11 // このオブジェクトを使ってXMLドキュメントを操作します。 12 $dom = new Dom\Document(); 13 14 // 2. 名前空間を含むサンプルXML文字列を定義します。 15 // 'b:article' 要素は "http://example.com/ns/books" という名前空間に属しています。 16 // 'book' および 'item' 要素は名前空間に属していません。 17 $xmlString = <<<XML 18<?xml version="1.0" encoding="UTF-8"?> 19<library xmlns:b="http://example.com/ns/books"> 20 <book id="bk001"> 21 <title>非名前空間の本 A</title> 22 <author>著者 X</author> 23 </book> 24 <b:article id="art001"> 25 <b:title>PHP入門</b:title> 26 <b:author>山田 太郎</b:author> 27 </b:article> 28 <book id="bk002"> 29 <title>非名前空間の本 B</title> 30 <author>著者 Y</author> 31 </book> 32 <b:article id="art002"> 33 <b:title>ウェブセキュリティ</b:title> 34 <b:author>佐藤 花子</b:author> 35 </b:article> 36 <item id="item001"> 37 <name>名前空間を持たないアイテム</name> 38 </item> 39</library> 40XML; 41 42 // 3. 定義したXML文字列をDOMドキュメントにロードします。 43 // ロードに失敗した場合のエラー処理も重要ですが、ここでは簡潔さを優先しています。 44 if (!$dom->loadXML($xmlString)) { 45 echo "エラー: XMLのロードに失敗しました。\n"; 46 return; 47 } 48 49 // 4. 名前空間 "http://example.com/ns/books" に属する "article" というローカル名を持つ要素を検索します。 50 // getElementsByTagNameNS の最初の引数には名前空間URIを指定し、 51 // 2番目の引数には要素のローカル名(プレフィックスを含まない名前)を指定します。 52 $namespaceUri = "http://example.com/ns/books"; 53 $localName = "article"; 54 echo "--- 検索条件: 名前空間URI '$namespaceUri', ローカル名 '$localName' ---\n"; 55 56 $articles = $dom->getElementsByTagNameNS($namespaceUri, $localName); 57 58 // 5. 検索結果(Dom\NodeList)をループして、各要素の情報を表示します。 59 if ($articles->count() > 0) { 60 echo $articles->count() . "件の記事が見つかりました。\n"; 61 foreach ($articles as $article) { 62 echo " ID: " . $article->getAttribute('id') . "\n"; 63 // 子要素も名前空間に属しているため、再度 getElementsByTagNameNS を使用して取得します。 64 $titles = $article->getElementsByTagNameNS($namespaceUri, 'title'); 65 if ($titles->count() > 0) { 66 echo " タイトル: " . $titles->item(0)->nodeValue . "\n"; 67 } 68 $authors = $article->getElementsByTagNameNS($namespaceUri, 'author'); 69 if ($authors->count() > 0) { 70 echo " 著者: " . $authors->item(0)->nodeValue . "\n"; 71 } 72 echo "\n"; 73 } 74 } else { 75 echo "指定された名前空間とローカル名の記事は見つかりませんでした。\n"; 76 } 77 78 echo "---------------------------------------------------\n"; 79 80 // 6. 名前空間に属さない "book" というローカル名を持つ要素を検索します。 81 // 名前空間に属さない要素を検索する場合は、最初の引数に null を指定します。 82 $localNameForBook = "book"; 83 echo "--- 検索条件: 名前空間なし (null), ローカル名 '$localNameForBook' ---\n"; 84 85 $books = $dom->getElementsByTagNameNS(null, $localNameForBook); 86 87 if ($books->count() > 0) { 88 echo $books->count() . "件の本が見つかりました。\n"; 89 foreach ($books as $book) { 90 echo " ID: " . $book->getAttribute('id') . "\n"; 91 // 名前空間を持たない子要素は getElementsByTagName で取得できます。 92 // getElementsByTagNameNS(null, 'title') を使用しても同じ結果になります。 93 $titles = $book->getElementsByTagName('title'); 94 if ($titles->count() > 0) { 95 echo " タイトル: " . $titles->item(0)->nodeValue . "\n"; 96 } 97 echo "\n"; 98 } 99 } else { 100 echo "指定された条件の本は見つかりませんでした。\n"; 101 } 102} 103 104// 関数を実行し、サンプルコードの動作を確認します。 105demonstrateGetElementsByTagNameNS();
Dom\Document::getElementsByTagNameNSメソッドは、PHPでXMLドキュメントを扱う際に、特定の「名前空間URI」と「ローカル名」を持つ要素を検索するために使用されます。このメソッドは、XMLドキュメント全体から指定された条件に合致するすべての要素を効率的に見つけ出すことができます。
第一引数$namespaceには、検索対象の名前空間URI(例: "http://example.com/ns/books")を指定します。もし名前空間を持たない要素を検索したい場合は、この引数に`null`を渡します。第二引数`$localName`には、要素のローカル名、つまりプレフィックス(例: b:)を含まない純粋な要素名(例: "article")を指定します。メソッドは、検索結果としてDom\NodeListオブジェクトを返します。これは、見つかった要素の集合を表すリストで、各要素にアクセスしてその属性や内容を取得できます。
サンプルコードでは、まず名前空間を含むXML文字列をDom\Documentオブジェクトに読み込みます。次に、"http://example.com/ns/books"という名前空間に属する"article"要素を検索し、見つかった各記事のID、タイトル、著者を順に表示しています。これにより、名前空間付きの要素を正確に抽出できることがわかります。さらに、名前空間に属さない"book"要素を検索する例も示されており、`$namespace`引数に`null`を指定することで、名前空間を持たない要素も適切に取得できることを実証しています。このように、`getElementsByTagNameNS`はXMLドキュメント内で特定の条件を持つ要素を柔軟に検索・操作するための強力なツールとなります。
getElementsByTagNameNSメソッドは、要素のプレフィックスではなく名前空間URIとローカル名を使って要素を検索する点に注意が必要です。最初の引数には名前空間のURL、二番目の引数にはプレフィックスを含まない純粋な要素名を指定してください。名前空間に属さない要素を検索する際は、最初の引数にnullを渡します。このメソッドは常にDom\NodeListオブジェクトを返し、一致する要素がない場合でも空のリストが返されるため、count()メソッドで件数を確認する必要があります。また、親要素が名前空間を持つ場合、その子要素も同じ名前空間に属していることが多いため、子要素の検索にもgetElementsByTagNameNSを適用する必要があるでしょう。XMLドキュメントのロードは失敗する可能性があるので、実運用では必ずエラー処理を組み込むようにしてください。