PHPでのXMLの処理は、特にサードパーティのインターフェイスでドッキングしたり、構成ファイルを処理したりする場合に一般的な要件です。 XML_PARSE()は、XMLデータを解析するためにPHPによって提供される根本的な関数です。ただし、多くのネストされた構造または複雑な形式でXMLを扱うと、注意しないと解析エラーが発生し、データが正しく読み取られないか、プログラムが直接クラッシュします。
この記事では、XML_PARSE()を使用してネストされたXMLを処理し、実用的なコードの例を提供する場合、一般的な解析エラーを回避する方法について説明します。
PHPのXML解析は通常、イベント駆動型モードを使用し、次の機能で使用されます。
xml_parse()
これが基本的なXML解析の例です。
<?php
$xml = <<<XML
<books>
<book>
<title>PHP プログラミング</title>
<author>チャン・サン</author>
</book>
<book>
<title>XML 実際の戦闘</title>
<author>li si</author>
</book>
</books>
XML;
$parser = xml_parser_create();
xml_set_element_handler($parser, "startElement", "endElement");
xml_set_character_data_handler($parser, "characterData");
function startElement($parser, $name, $attrs) {
echo "要素を開始します: $name\n";
}
function endElement($parser, $name) {
echo "終了要素: $name\n";
}
function characterData($parser, $data) {
if (trim($data)) {
echo "文字データ: $data\n";
}
}
if (!xml_parse($parser, $xml, true)) {
die("XML 間違い: " . xml_error_string(xml_get_error_code($parser)) .
" で " . xml_get_current_line_number($parser) . " わかりました");
}
xml_parser_free($parser);
?>
特に要素間にラインブレークまたはスペースがある場合、要素が深くネストされているときに、キャラクターダタコールバック関数が複数回トリガーされる場合があります。コンテンツは、キャッシュ変数を使用して収集し、 endElement()で処理する必要があります。
$depth = 0;
$currentTag = '';
$contentBuffer = [];
function startElement($parser, $name, $attrs) {
global $depth, $currentTag;
$depth++;
$currentTag = $name;
}
function endElement($parser, $name) {
global $depth, $currentTag, $contentBuffer;
if (isset($contentBuffer[$depth])) {
echo "要素 $name の値: " . trim($contentBuffer[$depth]) . "\n";
unset($contentBuffer[$depth]);
}
$depth--;
}
function characterData($parser, $data) {
global $depth, $contentBuffer;
if (!isset($contentBuffer[$depth])) {
$contentBuffer[$depth] = '';
}
$contentBuffer[$depth] .= $data;
}
一部のXMLには、コントロール文字、Unescaped & Symbolsなどの違法な文字が含まれている場合があります。現時点では、解析する前に前処理が必要です。
$xml = preg_replace('/[^\x09\x0A\x0D\x20-\x7F]/u', '', $xml); // 違法な文字を削除します
$xml = str_replace('&', '&', $xml); // エンコードされていない脱出 &
正当なXMLエンティティが破壊されないようにするために、繰り返し逃げないように注意してください。
パーサー作成時にXMLデータがUTF-8エンコードおよび指定されていることを確認してください。
$parser = xml_parser_create('UTF-8');
xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, 'UTF-8');
ネストされたXML構造が複雑な場合、スタック構造を使用してラベルレベルを記録して、その後の構造化処理を容易にすることをお勧めします。
$elementStack = [];
function startElement($parser, $name, $attrs) {
global $elementStack;
array_push($elementStack, $name);
}
function endElement($parser, $name) {
global $elementStack;
array_pop($elementStack);
}
スタックを介して、現在のパスまたは階層をリアルタイムで取得し、XML構造を表す多次元配列を構築することもできます。
外部のXMLソースの場合、例外処理を追加して、解析障害のためにページがクラッシュするのを防ぎます。
Processの障害に対する代替ソリューションとして、 simplexml_load_string()でlibxml_use_internal_errors()を使用します。
https://api.m66.net/data.xmlのようなインターフェイスからXMLを読み取る場合は、最初にfile_get_contents()を使用してコンテンツを読み取り、次に論理処理に影響を与えるネットワークエラーを回避するためにパーサーに渡してください。
$xmlContent = file_get_contents("https://api.m66.net/data.xml");
if ($xmlContent === false) {
die("ロードできません XML データ");
}
XML_PARSE()を使用してネストされたXMLを処理する場合、一般的な解析エラーは、一貫性のない文字データ、違法な文字、不規則なエンコード、または不明確な解析ロジックから得られることがよくあります。合理的なコーディング仕様、前処理、構造設計により、XML解析の堅牢性と安定性を大幅に改善できます。
基礎となる解析ロジックを習得すると、SimplexMLやDomDocumentなどの高度なXMLライブラリを使用できない場合、XMLデータ構造を効率的に処理するのにも役立ちます。
解析プロセスをさらに簡素化する必要がある場合は、クラスをカプセル化してパーサーとデータ収集ロジックを管理することを検討してください。これにより、コードの再利用と維持が可能になります。
関連タグ:
xml_parse