PHPを使用してXMLデータを処理する場合、 XML_PARSE()は比較的基本的な機能であり、PHPのXMLパーサー拡張機能(Expatに基づく)に属します。ただし、多くの開発者は、ネストされたタグを解析するために使用するときに正しく処理できない状況に遭遇することがよくあります。この記事では、この問題の原因を深く理解し、実用的な解決策を提供します。
XML_PARSE()は、イベント駆動型モデルを使用してXMLドキュメントを処理します。パーサーが開始タグ、エンドタグ、または文字データを読み取ると、対応するコールバック関数が呼び出されます。
サンプルの初期化コードは次のとおりです。
$parser = xml_parser_create();
xml_set_element_handler($parser, "startElement", "endElement");
xml_set_character_data_handler($parser, "characterData");
$data = '<book><title>PHP Guide</title><author>John</author></book>';
xml_parse($parser, $data, true);
xml_parser_free($parser);
この例では、パーサーは順番に起動、キャラクター、およびエンデレメントコールバック関数をトリガーします。
主な理由は次のとおりです。
多くの開発者は、ネストされたタグを扱う際に、解析された状態または構造を適切に維持できません。 XML_PARSE()はXMLツリー構造の作成に自動的に役立つため、ネストされたデータを手動で構築する必要があります。
たとえば、次のコードでは、ネストされたノードを正しく処理できません。
function startElement($parser, $name, $attrs) {
global $currentTag;
$currentTag = $name;
}
function characterData($parser, $data) {
global $currentTag;
echo "$currentTag: $data\n";
}
ネストされたタグでは、 $ currentTagは常に上書きされ、その結果、データが属するタグを識別できなくなります。
ネストされたXMLを解析するには、現在のタグパスを維持するためにスタックを使用することをお勧めします。
$tagStack = [];
function startElement($parser, $name, $attrs) {
global $tagStack;
array_push($tagStack, $name);
}
function endElement($parser, $name) {
global $tagStack;
array_pop($tagStack);
}
function characterData($parser, $data) {
global $tagStack;
$path = implode(' > ', $tagStack);
echo "[$path] $data\n";
}
このコードは、ネストされたタグの階層をより明確に表示できます。たとえば、
<article>
<header><title>ニュースタイトル</title></header>
<body>コンテンツセクション</body>
</article>
出力は次のとおりです。
[ARTICLE > HEADER > TITLE] ニュースタイトル
[ARTICLE > BODY] コンテンツセクション
xml_parse()に渡されたデータが不完全であるか、 is_finalパラメーター(つまり最後のパラメーター)が真であるほど真であると正しくマークされていない場合、解析も失敗します。
xml_parse($parser, $data, true); // 3番目のパラメーターは必要です true データが完了していることを示します
最も推奨される方法は、次のような高レベルのXMLパーサーを使用することです。
$xml = simplexml_load_string('<book><title>PHP Guide</title></book>');
echo $xml->title; // 出力: PHP Guide
$doc = new DOMDocument();
$doc->loadXML('<site><url>https://m66.net</url></site>');
$nodes = $doc->getElementsByTagName('url');
echo $nodes->item(0)->nodeValue; // 出力: https://m66.net
これらのパーサーは、あなたのためにノードのネストされた構造を処理しました。コードはより明確で、メンテナンスはより単純です。
XML_PARSE()はイベント駆動型モデルを使用し、構造化されたツリーを自動的に構築しないため、ネストされたタグを手動で処理する必要があります。
スタック構造を使用して現在のタグパスを追跡することをお勧めします。
プロジェクトでは、イベント駆動型メソッドが具体的に必要でない場合、ネストされたXMLを処理するためにSimplexMLまたはDomDocumentが推奨されます。
切り捨てを避けるために、着信データの完全性に注意してください。
XML解析は実際には複雑ではありません。重要なのは、適切なツールを選択し、その根本的な原則を理解することです。この記事が、実際の開発におけるネストされたXMLの問題にもっと対処するのに役立つことを願っています。