PHP-4種類のXMLファイルを解析する方法

9586 ワード

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であり、対応する値は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方式はコード行数が多いが,構想が明確で可読性が高いが,性能的には第1方式よりやや遅く,柔軟性が弱いことがわかる.XML ParserはPHP 4をサポートし、古いバージョンのシステムを使用するのに適しています.PHP 5環境については、以下の方法を優先しましょう.
2. SimpleXML
SimpleXMLは、PHP 5以降に提供される簡単で使いやすいxmlツールセットで、xmlを処理しやすいオブジェクトに変換したり、xmlデータの生成を組織したりすることができます.ただし、namespaceを含むxmlには適用されず、xmlフォーマットが完全であることを保証します.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. XMLReader
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. DOMDocument
DOMDocumentは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