現在の位置: ホーム> 最新記事一覧> xml_parseを介して複数のルート要素のxmlファイルを解析する方法

xml_parseを介して複数のルート要素のxmlファイルを解析する方法

M66 2025-04-28

XML標準では、Legal XMLドキュメントには1つのルート要素(ルート要素)のみが必要です。ただし、実際のアプリケーションシナリオでは、複数のルート要素を含むファイルなど、「非標準」形式でいくつかのXMLファイルが遭遇する場合があります。パーサーはデフォルトで標準のXML形式で動作するため、この構造はPHPのXML_PARSEパーサーを使用するときに問題を引き起こす可能性があります。

それでは、複数のルート要素を含むこのXMLファイルを正しく解析するにはどうすればよいですか?この記事では、この問題を段階的に解決することができます。

質問の例

このようなXMLファイルdata.xmlがあり、次のコンテンツがあると想像してください。

 <item>
  <name>Item 1</name>
</item>
<item>
  <name>Item 2</name>
</item>

標準XMLでは、2つのトップレベル<アイテム>要素が含まれているため、これは違法です。

方法1:単一のノードにパッケージします

一般的な解決策は、プログラム内のこれらのコンテンツに「仮想」ルートノードを人為的に追加することです。

 $xmlContent = file_get_contents('https://m66.net/data.xml');

// 仮想ルートノードをラップします
$xmlContent = "<root>$xmlContent</root>";

$parser = xml_parser_create();
xml_parse_into_struct($parser, $xmlContent, $values, $index);
xml_parser_free($parser);

print_r($values);

この方法で処理した後、 XML_PARSEはドキュメント全体を法的なXMLファイルとして扱うことができ、解析プロセスはエラーを報告しません。

方法2:ラインごとに複数のフラグメントを分析します

XMLファイルが非常に大きい場合、または一度にすべてを読みたくない場合は、 XML_PARSEのストリーミング方法を使用して、それを少しずつ解析することもできます。

 $parser = xml_parser_create();

function startElement($parser, $name, $attrs) {
    echo "Start: $name\n";
}

function endElement($parser, $name) {
    echo "End: $name\n";
}

function characterData($parser, $data) {
    echo "Data: " . trim($data) . "\n";
}

xml_set_element_handler($parser, "startElement", "endElement");
xml_set_character_data_handler($parser, "characterData");

$handle = fopen("https://m66.net/data.xml", "r");
if ($handle) {
    // それぞれを詰めます <item> ピース,セグメントごとに解析セグメントの仮想ルート要素を追加します
    $chunk = '';
    while (($line = fgets($handle)) !== false) {
        $chunk .= $line;
        if (strpos($line, '</item>') !== false) {
            $xml = "<root>$chunk</root>";
            xml_parse($parser, $xml, true);
            $chunk = '';
        }
    }
    fclose($handle);
}

xml_parser_free($parser);