PHPの組み込みXMLパーサー(Expatライブラリに基づく)は、複雑なXMLデータを扱う際に非常に強力なツールです。 XML_PARSER_CREATE()およびそれに付随する処理関数を介して、XML構造を柔軟に解析できます。特に、ネストレベルと多くの要素を備えたXMLドキュメントに直面している場合、カスタム要素ハンドラーは、解析の効率と読みやすさを大幅に向上させます。
この記事では、XML_SET_ELEMENT_HANDLER()を使用してXML要素プロセッサをカスタマイズし、複雑なXMLデータ構造をサンプルコードで解析する方法について詳しく説明します。
xml_parse()を使用してxmlストリームを解析する場合、 xml_set_element_handler()を介してパーサーに2つのコールバック関数を登録できます。
StartElementHandler :タグを開始するコールバック関数
EndelementHandler :タグを終了するためのコールバック関数
これらの2つの関数の署名は通常、次のとおりです。
function startElement($parser, $name, $attrs)
function endElement($parser, $name)
$ nameは現在のノードの名前と$ attrsが連想配列であり、ノードの属性を表します。
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>
各本のタイトル、著者、価格情報を抽出し、それを出力するパーサーを書きます。
<?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";
}
ステータス変数を使用してコンテキストを追跡<BR> $ currentTagや$ currentBookなどの状態変数は、深くネストされている場合に非常に重要であり、現在どのノードにあるかを判断するのに役立ちます。
ろ過文字をフィルターします
CharacterDataは多数のニューラインとスペースを受け取る場合があり、空のかどうかを判断するには()トリミングする必要があります。
繰り返しの割り当てを避けてください<BR> 一部のタグコンテンツは、複数のセグメント(特に長いテキスト)で返される場合があります。
名前空間を使用して複雑なXMLを処理します
XMLが名前空間を使用する場合、 XML_SET_START_NAMESPACE_DECL_HANDLER()などの高度なAPIを使用して解析に協力することをお勧めします。