PHP による XML 解析の 4 つの方法の詳細な紹介

高洛峰
リリース: 2017-01-06 15:16:38
オリジナル
1221 人が閲覧しました

PHP による xml 解析の 4 つの方法

XML 処理は開発プロセスで頻繁に使用されますが、PHP にはそれに対する豊富なサポートもあります。この記事では、Xml パーサー、SimpleXML、XMLReader、DOMDocument などの解析テクノロジの一部について簡単に説明します。 。

1. XML Expat パーサー:

XML パーサーは Expat XML パーサーを使用します。 Expat は、XML ドキュメントを一連のイベントとして扱うイベントベースのパーサーです。イベントが発生すると、指定された関数を呼び出してそれを処理します。 Expat は、ドキュメントにリンクされている DTD を無視する検証不要のパーサーです。ただし、ドキュメントの形式が適切でない場合は、エラー メッセージが表示されます。 Expat はイベントベースで検証がないため、高速であり、Web アプリケーションに適しています。

XML パーサーの利点は、XML ドキュメント全体をメモリにロードして処理するのではなく、解析しながら処理するため、パフォーマンスが優れていることです。しかし、まさにこのため、XML 構造を動的に調整したり、XML コンテキスト構造に基づいて複雑な操作を実行する必要があるユーザーには適していません。適切に構造化された XML ドキュメントを解析して処理したいだけであれば、このタスクを適切に完了できます。 XML パーサーは、US-ASCII、ISO-8859-1、UTF-8 の 3 つのエンコード形式のみをサポートしていることに注意してください。XML データが他のエンコード形式である場合は、まず、上記の 3 つのいずれかに変換する必要があります。
XML パーサーには一般的に 2 つのよく使用される解析メソッド (実際には 2 つの関数)、xml_parse_into_struct と xml_set_element_handler があります。

xml_parse_into_struct

このメソッドは、XML データを 2 つの配列に解析します:

index 配列 - Value 配列内の値の位置へのポインターが含まれます
value 配列 - 解析された XML からのデータが含まれます

これら 2 つの配列テキストで説明するのは少し面倒なので、例を見てみましょう (PHP 公式ドキュメントより)

$simple = "<para><note>simple note</note></para>";
$p = xml_parser_create();
xml_parse_into_struct($p, $simple, $vals, $index);
xml_parser_free($p);
echo "Index array\n";
print_r($index);
echo "\nVals array\n";
print_r($vals);
ログイン後にコピー

出力:

Index array
Array
(
  [PARA] => Array
    (
      [0] => 0
      [1] => 2
    )
 
  [NOTE] => Array
    (
      [0] => 1
    )
)
 
Vals array
Array
(
  [0] => Array
    (
      [tag] => PARA
      [type] => open
      [level] => 1
    )
 
  [1] => Array
    (
      [tag] => NOTE
      [type] => complete
      [level] => 2
      [value] => simple note
    )
 
  [2] => Array
    (
      [tag] => PARA
      [type] => close
      [level] => 1
    )
)
ログイン後にコピー

インデックス配列はタグ名を持つ key という名前で、対応する値はすべてを含む配列です。のタグ 値配列内の位置。次に、この位置から、このラベルに対応する値を見つけます。

XML 内の各データセットの形式が異なっており、完全に統一できない場合、コードを記述するときに注意する必要があり、間違った結果が得られる可能性があります。たとえば、次の例:

$xml = &#39;
<infos>
<para><note>note1</note><extra>extra1</extra></para>
<para><note>note2</note></para>
<para><note>note3</note><extra>extra3</extra></para>
</infos>
&#39;;
 
$p = xml_parser_create();
xml_parse_into_struct($p, $xml, $values, $tags);
xml_parser_free($p);
$result = array();
ログイン後にコピー
//下面的遍历方式有bug隐患
for ($i=0; $i<3; $i++) {
 $result[$i] = array();
 $result[$i]["note"] = $values[$tags["NOTE"][$i]]["value"];
 $result[$i]["extra"] = $values[$tags["EXTRA"][$i]]["value"];
}
print_r($result);
ログイン後にコピー

上記の方法でトラバースすると、コードは単純に見えますが、隠れた危険性があります。最も致命的なのは、間違った結果が得られることです (extra3 が 2 番目のパラグラフに実行されます)。したがって、より厳密な方法でトラバースする必要があります:

$result = array();
$paraTagIndexes = $tags[&#39;PARA&#39;];
$paraCount = count($paraTagIndexes);
for($i = 0; $i < $paraCount; $i += 2) {
 $para = array();
 //遍历para标签对之间的所有值
 for($j = $paraTagIndexes[$i]; $j < $paraTagIndexes[$i+1]; $j++) {
  $value = $values[$j][&#39;value&#39;];
  if(empty($value)) continue;
 
  $tagname = strtolower($values[$j][&#39;tag&#39;]);
  if(in_array($tagname, array(&#39;note&#39;,&#39;extra&#39;))) {
   $para[$tagname] = $value;
  }
 }
 $result[] = $para;
}
ログイン後にコピー

実際、私は xml_parse_into_struct 関数をほとんど使用しないため、上記のいわゆる「厳密な」コードが保持されていない場合、他の状況でバグが発生することになります。 - -|

xml_set_element_handler

このメソッドは、要素の開始と終了を処理するパーサーのコールバック関数を設定します。パーサーのデータを設定するために使用されるコールバック関数 xml_set_character_data_handler も含まれています。この方法で記述されたコードはより明確で、保守が容易になります。

例:

$xml = <<<XML
<infos>
<para><note>note1</note><extra>extra1</extra></para>
<para><note>note2</note></para>
<para><note>note3</note><extra>extra3</extra></para>
</infos>
XML;
 
$result = array();
$index = -1;
$currData;
 
function charactor($parser, $data) {
 global $currData;
 $currData = $data;
}
 
function startElement($parser, $name, $attribs) {
 global $result, $index;
 $name = strtolower($name);
 if($name == &#39;para&#39;) {
  $index++;
  $result[$index] = array();
 }
}
 
function endElement($parser, $name) {
 global $result, $index, $currData;
 $name = strtolower($name);
 if($name == &#39;note&#39; || $name == &#39;extra&#39;) {
  $result[$index][$name] = $currData;
 }
}
 
$xml_parser = xml_parser_create();
xml_set_character_data_handler($xml_parser, "charactor");
xml_set_element_handler($xml_parser, "startElement", "endElement");
if (!xml_parse($xml_parser, $xml)) {
 echo "Error when parse xml: ";
 echo xml_error_string(xml_get_error_code($xml_parser));
}
xml_parser_free($xml_parser);
 
print_r($result);
ログイン後にコピー

set ハンドラー メソッドはコード行数が多いものの、アイデアが明確で読みやすさが優れていますが、最初のメソッドよりもパフォーマンスが若干遅く、柔軟性が低いことがわかります。 XML パーサーは PHP4 をサポートしており、古いバージョンを使用するシステムに適しています。 PHP5環境の場合は以下の方法を優先してください。

2. SimpleXML

SimpleXMLは、PHP5以降に提供されたシンプルで使いやすいxmlツールのセットで、xmlを処理に便利なオブジェクトに変換したり、xmlデータを整理して生成したりすることができます。ただし、名前空間を含む XML には適用されず、XML は整形式である必要があります。これは、simplexml_import_dom、simplexml_load_file、simplexml_load_string の 3 つのメソッドを提供します。関数名は関数を直感的に説明します。 3 つの関数はすべて SimpleXMLElement オブジェクトを返し、データは SimpleXMLElement 操作を通じて読み取り/追加されます。

$string = <<<XML
<?xml version=&#39;1.0&#39;?>
<document>
 <cmd>login</cmd>
 <login>imdonkey</login>
</document>
XML;
 
$xml = simplexml_load_string($string);
print_r($xml);
$login = $xml->login;//这里返回的依然是个SimpleXMLElement对象
print_r($login);
$login = (string) $xml->login;//在做数据比较时,注意要先强制转换
print_r($login);
ログイン後にコピー

SimpleXML の利点は、開発が簡単であることです。欠点は、処理前に XML 全体をメモリにロードするため、大量のコンテンツを含む XML ドキュメントを解析できない可能性があることです。小さなファイルを読み取っていて、XML に名前空間が含まれていない場合は、SimpleXML が適切な選択です。

3. XMLReader

XMLReader も PHP5 以降の拡張機能です (5.1 以降はデフォルトでインストールされます) ドキュメントフロー内をカーソルのように移動し、各ノードで停止するため、非常に柔軟な操作が可能です。入力への高速かつ非キャッシュのストリーミング アクセスを提供し、ストリームまたはドキュメントを読み取ることができるため、ユーザーはそこからデータを抽出し、アプリケーションにとって意味のないレコードをスキップできます。

Google Weather API を使用して情報を取得する例では、XMLReader の使用が示されています。詳細については、公式ドキュメントを参照してください。

$xml_uri = &#39;http://www.google.com/ig/api?weather=Beijing&hl=zh-cn&#39;;
$current = array();
$forecast = array();
 
$reader = new XMLReader();
$reader->open($xml_uri, &#39;gbk&#39;);
while ($reader->read()) {
 //get current data
 if ($reader->name == "current_conditions" && $reader->nodeType == XMLReader::ELEMENT) {
  while($reader->read() && $reader->name != "current_conditions") {
   $name = $reader->name;
   $value = $reader->getAttribute(&#39;data&#39;);
   $current[$name] = $value;
  }
 }
 
 //get forecast data
 if ($reader->name == "forecast_conditions" && $reader->nodeType == XMLReader::ELEMENT) {
  $sub_forecast = array();
  while($reader->read() && $reader->name != "forecast_conditions") {
   $name = $reader->name;
   $value = $reader->getAttribute(&#39;data&#39;);
   $sub_forecast[$name] = $value;
  }
  $forecast[] = $sub_forecast;
 }
}
$reader->close();
ログイン後にコピー

XMLReader は XML パーサーに似ていますが、どちらも読み取り中に動作します。大きな違いは、SAX モデルが「プッシュ」モデルであり、アナライザーがイベントをアプリケーションにプッシュし、新しいノードが読み取られるたびにアプリケーションに通知することです。 .プログラムである一方、XmlReader を使用するアプリケーションは、より優れた制御性でリーダーから自由にノードを抽出できます。
XMLReader は libxml に基づいているため、一部の関数のドキュメントを参照して、お使いの libxml バージョンに適用できるかどうかを確認してください。

4. DOMDocument

DOMDocument は、PHP5 以降にリリースされた DOM 拡張機能の一部でもあり、html/xml の作成または解析に使用できます。現在、utf-8 エンコーディングのみをサポートしています。

$xmlstring = <<<XML
<?xml version=&#39;1.0&#39;?>
<document>
 <cmd attr=&#39;default&#39;>login</cmd>
 <login>imdonkey</login>
</document>
XML;
 
$dom = new DOMDocument();
$dom->loadXML($xmlstring);
print_r(getArray($dom->documentElement));
 
function getArray($node) {
 $array = false;
 
 if ($node->hasAttributes()) {
  foreach ($node->attributes as $attr) {
   $array[$attr->nodeName] = $attr->nodeValue;
  }
 }
 
 if ($node->hasChildNodes()) {
  if ($node->childNodes->length == 1) {
   $array[$node->firstChild->nodeName] = getArray($node->firstChild);
  } else {
   foreach ($node->childNodes as $childNode) {
   if ($childNode->nodeType != XML_TEXT_NODE) {
    $array[$childNode->nodeName][] = getArray($childNode);
   }
  }
 }
 } else {
  return $node->nodeValue;
 }
 return $array;
}
ログイン後にコピー

从函数名上看感觉跟JavaScript很像,应该是借鉴了一些吧。DOMDocument也是一次性将xml载入内存,所以内存问题同样需要注意。PHP提供了这么多的xml处理方式,开发人员在选择上就要花些时间了解,选择适合项目需求及系统环境、又便于维护的方法。

感谢阅读,希望能帮助到大家,谢谢大家对本站支持!

更多php 解析xml 的四种方法详细介绍相关文章请关注PHP中文网!

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のおすすめ
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート