PHPプログラムに関する各種メモ書き

PHPでXMLパースしてオブジェクトまたはハッシュに変換する

● 1. PHPでXMLをパースしてハッシュ(配列)に変換する

こちらの関数を使用すると簡単に取得できます。
が、次の <dddd>タグのような attributes が取得できません。( Id="id:pass" が無視される)
<eeee>タグ内の attributes は取得できます。

$xml = <<< DOC_END
<aaaa Version="1.0">
   <bbb>
     <cccc>
       <dddd Id="id:pass">テスト</dddd>
       <eeee name="hearaman" age="24" />
     </cccc>
   </bbb>
</aaaa>
DOC_END;
function xml2array($xml){
    $xml = preg_replace('/(<\/?)\w+:([^>]*>)/', '$1$2', $xml); //get rid of namespaces
    $xml = simplexml_load_string($xml);
    return json_decode(json_encode($xml),true); //use built-in stuff
}

結果

Array
(
    [@attributes] => Array
        (
            [Version] => 1.0
        )
    [bbb] => Array
        (
            [cccc] => Array
                (
                    [dddd] => テスト
                    [eeee] => Array
                        (
                            [@attributes] => Array
                                (
                                    [name] => hearaman
                                    [age] => 24
                                )
                        )
                )
        )
)

● 2. PHPでXMLをパースしてハッシュ(配列)に変換する

完璧に取得したい場合はこちらがおすすめです。

function XMLtoArray($xml) {
    $previous_value = libxml_use_internal_errors(true);
    $dom = new DOMDocument('1.0', 'UTF-8');
    $dom->preserveWhiteSpace = false;
    $dom->loadXml($xml);
    libxml_use_internal_errors($previous_value);
    if (libxml_get_errors()) {
        return [];
    }
    return DOMtoArray($dom);
}

function DOMtoArray($root) {
    $result = array();
    if ($root->hasAttributes()) {
        $attrs = $root->attributes;
        foreach ($attrs as $attr) {
            $result['@attributes'][$attr->name] = $attr->value;
        }
    }
    if ($root->hasChildNodes()) {
        $children = $root->childNodes;
        if ($children->length == 1) {
            $child = $children->item(0);
            if (in_array($child->nodeType,[XML_TEXT_NODE,XML_CDATA_SECTION_NODE])) {
                $result['_value'] = $child->nodeValue;
                return count($result) == 1
                    ? $result['_value']
                    : $result;
            }

        }
        $groups = array();
        foreach ($children as $child) {
            if (!isset($result[$child->nodeName])) {
                $result[$child->nodeName] = DOMtoArray($child);
            } else {
                if (!isset($groups[$child->nodeName])) {
                    $result[$child->nodeName] = array($result[$child->nodeName]);
                    $groups[$child->nodeName] = 1;
                }
                $result[$child->nodeName][] = DOMtoArray($child);
            }
        }
    }
    return $result;
}

結果

Array
(
    [aaaa] => Array
        (
            [@attributes] => Array
                (
                    [Version] => 1.0
                )
            [bbb] => Array
                (
                    [cccc] => Array
                        (
                            [dddd] => Array
                                (
                                    [@attributes] => Array
                                        (
                                            [Id] => id:pass
                                        )
                                    [_value] => テスト
                                )
                            [eeee] => Array
                                (
                                    [@attributes] => Array
                                        (
                                            [name] => hearaman
                                            [age] => 24
                                        )
                                )
                        )
                )
        )
)

引用元 : https://goo.gl/Ko7fwC

● 名前空間を削除する

名前空間の名前が付いてくるのが邪魔な場合は変換前に次の1行を噛ませて名前空間を削除しておきましょう。

$xml = preg_replace('/(<\/?)\w+:([^>]*>)/', '$1$2', $xml); //get rid of namespaces

● 3. PHPでXMLをパースしてオブジェクトまたはハッシュに変換する

よくネットで見かけるやり方です。通常これでも問題ないのですが、 <ns2:ItemDimensions> のようなネーム空間を持つXMLを変換できない時があります。

$xml = simplexml_load_string($html);
$xml_array = json_decode( json_encode( $xml ), TRUE );

● Message: simplexml_load_string(): Entity: line 1: parser error : Unsupported encoding x-sjis-cp932 エラーとなる場合の対処

返される xml が x-sjis-cp932 エンコーディングの場合エラーとなるので、次のように変換する。

 $data = mb_convert_encoding($data,"UTF-8");
 $data = str_replace("x-sjis-cp932","UTF-8",$data);

関連エントリー

No.422
02/01 17:07

edit

PEAR
XML