XMLのパース DOMDocument、simplexml_load_string

namespace(名前空間)があると面倒

作成日:2021-05-07, 更新日:2021-05-10

基本

XMLの解析にはいくつか方法がある
・simplexml_load_string
・DOMDocument
※他にもあるっぽい。

▼namespace(名前空間)があるときはちょっと面倒。
・simplexml_load_string - 名前空間を指定してあげる必要あり
・DOMDocument - 名前空間を使わずとも取得可能

名前空間がないとき

▼こんなヤツ

~ 略 ~
<foo 〇〇〇〇>丸ごとシマウマ</foo>
~ 略 ~

XMLの文字列を「simplexml_load_string()」に放り込むだけでOK

$xml_str = 〇〇〇;
$xml_obj = simplexml_load_string($xml_str);
var_dump($xml_obj);

パースしたいXML

▼こんなヤツ

~ 略 ~
<hoge:foo 〇〇〇〇>丸ごとシマウマ</hoge:foo>
~ 略 ~

※上記の場合「hogeが名前空間」で「fooがlocalName」になる

simplexml_load_string - 名前空間を指定する

ひと手間加える必要がある

$xml_str = 〇〇〇;
$xml_obj = simplexml_load_string($xml_str);

// children()に名前空間である「hoge」をつっこんで、localNameである「foo」で取得
echo $xml_obj->children('hoge', true)->foo; // 「丸ごとシマウマ」が出力される

DOMDocument - 名前空間を指定したくない

名前空間を使わずにlocalNameだけでどうにかする

$xml_str = 〇〇〇;
$xml_obj = new DOMDocument;
$xml_obj->loadXML($xml_str);

foreach( $xml_obj->getElementsByTagName('foo') as $foo ){
  // localNameである「foo」で取得
  echo $foo->localName . ' - ' . $foo->nodeValue; // 「foo - 丸ごとシマウマ」みたいな感じで出力される
}

子要素

▼こんな感じのXML

~ 略 ~
<hoge:foo 〇〇〇〇>
  <bar:abc 〇〇〇〇>もちベーコン</bar:abc>
</hoge:foo>
~ 略 ~

▼良い方法があると思うけど・・・スケジュールの都合で未調査

$xml_str = 〇〇〇;
$xml_obj = new DOMDocument;
$xml_obj->loadXML($xml_str);

foreach( $xml_obj->getElementsByTagName('foo') as $foo ){
  foreach( $foo->getElementsByTagName('abc') as $abc ){
    echo $abc->localName . ' - ' . $abc->nodeValue; // 「abc - もちベーコン」みたいな感じで出力される
  }
}

XMLの解析失敗対応 - libxml_get_errors()

変なXMLを解析しようとしたときのエラー対応

▼DOMDocument、simplexml_load_stringのどちらもlibxml_get_errors()でエラーを取得可能

libxml_use_internal_errors(true); // ユーザーによるエラー処理の有効化

$xml_str = 〇〇〇;

// ▼simplexml_load_stringのとき
// $xml_obj = simplexml_load_string($xml_str);
// if ($xml_obj === false) {
//   foreach(libxml_get_errors() as $error) {
//     // var_dump($error);
//     echo $error->message;
//   }
//   libxml_clear_errors();
//   exit;
// }

// ▼DOMDocumentのとき
$xml_obj = new DOMDocument;
if ( !$xml_obj->loadXML($xml_str) ) {
  foreach (libxml_get_errors() as $error) {
    // var_dump($error);
    echo $error->message;
  }
  libxml_clear_errors();
  exit;
}