2011-06-03 8 views
3

は、言う:PHPが不足しているXMLデータの取り扱い

<note><from>Me</from><to>someone</to><message>hello</message></note> 

<note><from>Me</from><to></to><message>Need milk & eggs</message></note> 

<note><from>Me</from><message>Need milk & eggs</message></note> 

と私はSimpleXMLをを使用していますが、空/不在のタグが自動的にありますことを簡単なXMLチェックを持ってする方法はありますか?

私は、出力がなりたい:

FROM TO  MESSAGE 
Me someone hello 
Me NULL Need milk & eggs 
Me NULL Need milk & eggs 

は今、私は手動でそれをやっていると私はすぐに長いxmlファイルのためにそれを行うには非常に長い時間がかかるだろうことに気づきました。

私の現在のサンプルコード:

$xml = simplexml_load_string($string); 
if ($xml->from != "") {$out .= $xml->from."\t"} else {$out .= "NULL\t";} 
//repeat for all children, checking by name 

は時々注文が持つXMLがあるかもしれない、なども異なります。

<note><message>pick up cd</message><from>me</from></note> 

はとても子供を反復処理し、インデックス数doesnの」でチェック仕事。

私が扱っている実際のxmlファイルはそれぞれ何千行もあるので、明らかにすべてのタグをコーディングすることはできません。あなたはDTD(Document Type Definition)を必要とするよう

+0

私はあなたのXMLがうまく構成されていないと主張します。技術的には、空のフィールドを表すタグを最小限にする必要があります。 –

+0

あなたは空のタグや欠けているタグではなく、不在を意味します。 –

+0

ああ、両方、私はそれを編集します – NorthGuard

答えて

1

代わりにDOMDocumentを使用できます。私は、<note>要素を、キーというXMLタグ名を使って配列に分割する簡単なデモを作成しました。結果の配列を反復して出力を作成することができます。

アンパサンドをHTMLエンティティ(&amp;)に置き換えて無効なXMLを修正しました。

<?php 
    libxml_use_internal_errors(true); 
    $xml = <<<XML 
<notes> 
<note><from>Me</from><to>someone</to><message>hello</message></note> 
<note><from>Me</from><to></to><message>Need milk &amp; eggs</message></note> 
<note><from>Me</from><message>Need milk &amp; eggs</message></note> 
<note><message>pick up cd</message><from>me</from></note> 
</notes> 
XML; 

    function getNotes($nodelist) { 
     $notes = array(); 

     foreach ($nodelist as $node) { 
      $noteParts = array(); 

      foreach ($node->childNodes as $child) { 
       $noteParts[$child->tagName] = $child->nodeValue; 
      } 

      $notes[] = $noteParts; 
     } 

     return $notes; 
    } 

    $dom = new DOMDocument(); 
    $dom->recover = true; 
    $dom->loadXML($xml); 
    $xpath = new DOMXPath($dom); 
    $nodelist = $xpath->query("//note"); 
    $notes = getNotes($nodelist); 

    print_r($notes); 
?> 

編集:あなたが$noteParts = array('from' => null, 'to' => null, 'message' => null);$noteParts = array();に変更すると、それは常にキーのフルセットを作成します。

+0

print_rから、出力配列にはノートキーを持つ空の値の代わりに最後の2つのデータセットのノートタグがありませんが、DOM :: Recoverは興味深いようです。 – NorthGuard

+0

Heh、それは最初の2つのノートだけでテストするために私に教えてくれるでしょう:-)私は上の答えに新しい配列宣言を追加しました。 'DOM :: Recover'は実際に無効なXML('& ')を解析することを許可しました。私はデモを書いていたときに忘れてしまい、なぜそれがうまくいかないのか疑問に思ったので、あなたの入力XMLを更新しました! – andyb

+0

ええと...私は、DOMは確かにこれらの答えの両方から行く方法だと思います。 – NorthGuard

2

これは、要素が必要とされているオプション、それらに含まれることができるか、など

のDTDができるXMLファイルの必要なフォーマットを定義し、指定したであろう、聞こえますXMLファイルを処理する前にXMLファイルを検証するために使用することができます。

残念ながら、PHPのsimplexmlライブラリはDTDで何もしませんが、DomDocumentライブラリはそうしていますので、代わりにそれを使用してください。

私はDTDファイルの作成方法を研究するために、別のエクササイズとして残します。あなたがそれについてもっと助けが必要な場合は、別の質問としてそれを尋ねることをお勧めします。

+0

私が扱っているxmlにはDTD urlが添付されていますが、DOM関数を見れば、見つからない/空のoptinalタグを印刷する方法はありますか?タグが存在するかどうかわからない同じ問題が残っていると思います。ノード名を特に照会しなければ、そのタグが存在しないことが有効かどうかだけを知ることになります。 – NorthGuard

+0

@inTide:すでにDTDを持っていたことは分かりませんでした。 DTDでタグが必須であると指定されている場合、タグがない場合はエラーが発生します。ただし、DTDで必須ではない場合はエラーは発生しません。その場合は、おそらくあなたを助けません。より厳しいルールで独自のDTDを定義し、それに対して検証することはできますが、本当に正しいアプローチであるかどうかはわかりません。 – Spudley

+2

DTDは厄介です。検証のためにRelaxNGを好むでしょう(PHPもサポートしています)。 –