現在の位置: ホーム> 最新記事一覧> 複雑なXMLデータ構造に合わせてXML_PARSEの要素プロセッサをカスタマイズする方法

複雑なXMLデータ構造に合わせてXML_PARSEの要素プロセッサをカスタマイズする方法

M66 2025-05-13

PHPの組み込みXMLパーサー(Expatライブラリに基づく)は、複雑なXMLデータを扱う際に非常に強力なツールです。 XML_PARSER_CREATE()およびそれに付随する処理関数を介して、XML構造を柔軟に解析できます。特に、ネストレベルと多くの要素を備えたXMLドキュメントに直面している場合、カスタム要素ハンドラーは、解析の効率と読みやすさを大幅に向上させます。

この記事では、XML_SET_ELEMENT_HANDLER()を使用してXML要素プロセッサをカスタマイズし、複雑なXMLデータ構造をサンプルコードで解析する方法について詳しく説明します。

1。XML要素プロセッサとは何ですか?

xml_parse()を使用してxmlストリームを解析する場合、 xml_set_element_handler()を介してパーサーに2つのコールバック関数を登録できます。

  • StartElementHandler :タグを開始するコールバック関数

  • EndelementHandler :タグを終了するためのコールバック関数

これらの2つの関数の署名は通常、次のとおりです。

 function startElement($parser, $name, $attrs)
function endElement($parser, $name)

$ nameは現在のノードの名前と$ attrsが連想配列であり、ノードの属性を表します。

2。例:ネストされた複雑なXMLデータを解析します

APIから次の形式でXMLデータを取得するとします。

 <catalog>
    <book id="001">
        <title>PHP 開発慣わかりました</title>
        <author>チャン・サン</author>
        <price currency="CNY">89.00</price>
    </book>
    <book id="002">
        <title>詳細な理解 XML</title>
        <author>li si</author>
        <price currency="CNY">75.50</price>
    </book>
</catalog>

各本のタイトル、著者、価格情報を抽出し、それを出力するパーサーを書きます。

3。カスタムプロセッサの実装

<?php

$xmlData = file_get_contents('https://m66.net/api/books.xml');

// 解析結果を保存するために使用されます
$books = [];
$currentBook = [];
$currentTag = "";

// 作成する XML パーサー
$parser = xml_parser_create("UTF-8");

// 開始タグとエンドタグの処理関数を設定します
xml_set_element_handler($parser, "startElement", "endElement");

// 文字データ処理機能を設定します
xml_set_character_data_handler($parser, "characterData");

// 设置パーサー参数
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false); // ラベルケースの一貫性を保ちます

// 処理機能を定義します
function startElement($parser, $name, $attrs) {
    global $currentBook, $currentTag;

    $currentTag = $name;

    if ($name == "book") {
        $currentBook = [
            "id" => $attrs['id'] ?? null,
            "title" => "",
            "author" => "",
            "price" => "",
            "currency" => ""
        ];
    }

    if ($name == "price" && isset($attrs['currency'])) {
        $currentBook['currency'] = $attrs['currency'];
    }
}

function endElement($parser, $name) {
    global $books, $currentBook, $currentTag;

    if ($name == "book") {
        $books[] = $currentBook;
        $currentBook = [];
    }

    $currentTag = "";
}

function characterData($parser, $data) {
    global $currentBook, $currentTag;

    $data = trim($data);
    if (empty($data)) return;

    switch ($currentTag) {
        case "title":
            $currentBook["title"] .= $data;
            break;
        case "author":
            $currentBook["author"] .= $data;
            break;
        case "price":
            $currentBook["price"] .= $data;
            break;
    }
}

// 解析を実わかりましたします
if (!xml_parse($parser, $xmlData, true)) {
    die(sprintf("XML 間違い: %s で %d わかりました",
        xml_error_string(xml_get_error_code($parser)),
        xml_get_current_line_number($parser)));
}

xml_parser_free($parser);

// 出力分析の結果
foreach ($books as $book) {
    echo "本のタイトル: {$book['title']}\n";
    echo "著者: {$book['author']}\n";
    echo "価格: {$book['price']} {$book['currency']}\n";
    echo "------------------------\n";
}

4。最適化の手法と提案

  1. ステータス変数を使用してコンテキストを追跡<BR> $ currentTag$ currentBookなどの状態変数は、深くネストされている場合に非常に重要であり、現在どのノードにあるかを判断するのに役立ちます。

  2. ろ過文字をフィルターします
    CharacterDataは多数のニューラインとスペースを受け取る場合があり、空のかどうかを判断するには()トリミングする必要があります。

  3. 繰り返しの割り当てを避けてください<BR> 一部のタグコンテンツは、複数のセグメント(特に長いテキスト)で返される場合があります

  4. 名前空間を使用して複雑なXMLを処理します
    XMLが名前空間を使用する場合、 XML_SET_START_NAMESPACE_DECL_HANDLER()などの高度なAPIを使用して解析に協力することをお勧めします。