php解析xmlの4つの方法(回転)

9384 ワード

XML処理は開発の過程でよく出会うもので、PHPはそれに対しても豊富な支持があって、本文はただその中のいくつかの解析技術に対して簡単に説明するだけで、Xml parser、SimpleXML、XML Reader、DOMDocumentを含む.1. XML Expat Parser:XML Parser Expat XML解析器を使用します.Expatは、XMLドキュメントを一連のイベントと見なすイベントベースの解析器です.イベントが発生すると、指定した関数を呼び出して処理します.Expatは、ドキュメントにリンクされているDTDを無視する検証されていない解析器です.ただし、ドキュメントの形式が悪い場合は、エラーメッセージで終了します.イベントベースで検証されていないため、Expatは迅速でWebアプリケーションに適しています.XML Parserの利点は、xmlドキュメント全体をメモリにロードしてから処理するのではなく、解析しながら処理するため、パフォーマンスが良いことです.しかし、そのため、xml構造を動的に調整したり、xmlコンテキスト構造に基づいて複雑な操作をしたりする必要はありません.構造の良いxmlドキュメントを解析的に処理するだけであれば、タスクをうまく完了できます.XML Parserは、US-ACSCII、ISO-8859-1、UTF-8の3つの符号化フォーマットしかサポートしていません.xmlデータが他の符号化であれば、上記の3つの1つに変換する必要があります.XML Parserでよく使われる解析方法は大きく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
"; print_r($index); echo "
Vals array
"; print_r($vals);
出力:Index arrayArray([PARA]=>Array(            [0] => 0            [1] => 2        )    [NOTE] => Array        (            [0] => 1        ))Vals arrayArray(    [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        ))ここでindex配列はラベル署名keyであり、対応する値は1つの配列であり、value配列中のすべてのラベルの位置が含まれている.そして、この位置を通じて、このラベルに対応する値を見つける.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>
';

$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);
上記のように遍歴すると、コードは簡単そうに見えますが、危機を隠すのは、最も致命的なのは間違いの結果を得ることです(extra 3は2番目のparaに走っています).だから、比較的厳格な方法で遍歴します:
$result = array();
$paraTagIndexes = $tags['PARA'];
$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]['value'];
    if(empty($value)) continue;

    $tagname = strtolower($values[$j]['tag']);
    if(in_array($tagname, array('note','extra'))) {
      $para[$tagname] = $value;
    }
  }
  $result[] = $para;
}
実は私はxml_parse_into_struct関数をあまり使いません.だから、上のいわゆる「厳格」のコードが揃っていない場合は他にもバグがあります.--|xml_set_element_handlerこの方式はparserに処理要素の開始、要素の終了を設定するコールバック関数です.xml_set_character_data_handlerはparserにデータを設定するコールバック関数もあります.この方式で書かれたコードは比較的明確で、メンテナンスに便利です.Example:
$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 == 'para') {
    $index++;
    $result[$index] = array();
  }
}

function endElement($parser, $name) {
  global $result, $index, $currData;
  $name = strtolower($name);
  if($name == 'note' || $name == 'extra') {
    $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 handler方式コードの行数は多いが、構想がはっきりしていて、読みやすさが優れているが、性能的には第一の方式よりやや遅く、柔軟性が弱い.XML ParserはPHP 4をサポートしており、古いバージョンのシステムを使用するのに適している.PHP 5環境については、以下の方法を優先的に考慮しよう.2.SimpleXML LSimpleXMLはPHP 5後に提供される簡単で使いやすいxmlツールセットであり、xmlを方に変換することができる処理するオブジェクトは、xmlデータの生成を組織することもできます.ただし、namespaceを含むxmlには適用されず、xmlフォーマットが完全であることを保証する必要があります(well-formed).3つの方法が用意されています.simplexml_import_dom、simplexml_load_file、simplexml_load_stringです.関数名は直感的に関数の役割を説明しています.3つの関数はSimpleXMLオブジェクトを返し、データの読み取り/追加はSimpleXMLによって操作されます.
$string = <<<XML
<?xml version='1.0'?>
<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にもnamespaceが含まれていない場合は、SimpleXMLが良い選択です.
3.XML Reader XML ReaderもPHP 5以降の拡張(5.1以降デフォルトインストール)を選択すると、カーソルのようにドキュメント・ストリーム内を移動し、各ノードで停止し、操作が柔軟になります.入力への高速およびキャッシュされていないストリーム・アクセスを提供し、ストリームまたはドキュメントを読み取り、ユーザーがデータを抽出し、アプリケーションの意図しないレコードをスキップすることができます.Google天気apiを使用して情報を取得する例として、XML Readerの使用を示します.を参照してください.
$xml_uri = 'http://www.google.com/ig/api?weather=Beijing&hl=zh-cn';
$current = array();
$forecast = array();

$reader = new XMLReader();
$reader->open($xml_uri, 'gbk');
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('data');
      $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('data');
      $sub_forecast[$name] = $value;
    }
    $forecast[] = $sub_forecast;
  }
}
$reader->close();
XML ReaderとXML Parserは似ていますが、どちらも読みながら操作されています.大きな違いはSAXモデルが「プッシュ」であることです.アナライザがイベントをアプリケーションにプッシュし、新しいノードを読み込むたびにアプリケーションに通知するモデルです.XmlReaderを使用するアプリケーションは、リーダからノードを任意に抽出できます.制御性が向上します.XML Readerはlibxmlに基づいているため、libxmlバージョンに適用されるかどうかをドキュメントを参照する関数もあります.4.DOMDocumentDOMDocumentかPHP 5以降に発売されるDOMか拡張の一部はhtml/xmlを作成または解析するために使用され、現在はutf-8符号化のみがサポートされている.
$xmlstring = <<<XML
<?xml version='1.0'?>
<document>
  <cmd attr='default'>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処理方式を提供しており、開発者は選択に時間がかかるプロジェクトのニーズとシステム環境に適合し、メンテナンスが容易な方法を選択します.
http://www.phpzh.com/archives/525/2