PHP SimpleXML のスニペット集

このページは、PHP の SimpleXML のスニペットなどをまとめる予定のページです。

目次

注意

  • コードのライセンスは CC0 (クレジット表示不要、改変可、商用可) です。

スニペット

XML 読み込み (文字列から)

$xmlString = '<response>
    <item id="item-0001" class="book">
        <title>test item 1</title>
        <url>https://example.com/1</url>
    </item>
    <item id="item-0002" class="book">
        <title>test item 2</title>
        <url>https://example.com/2</url>
    </item>
    <item id="item-0003" class="book">
        <title>test item 3</title>
        <url>https://example.com/3</url>
    </item>
</response>';
$xml = simplexml_load_string($xmlString);

XML 読み込み (ファイルから)

$xml = simplexml_load_file('/path/to/file.xml');

値のアクセス

$item = $xml->item[0]; // 子要素の先頭の <item>
$name = $item->getName(); // 要素名 (ローカル名。'item')
$id = (string)$item->attributes()->id; // $item の id 属性 (文字列に変換。'item-0001')
$url = (string)$item->url; // $item 内の <url> (文字列に変換。'https://example.com/1')

※ 要素の名前空間 URI や接頭辞を取得することはできないようですが、dom_import_simplexml() で DOMElement に変換して namespaceURI, prefix で取得することはできます。

子要素の反復処理

同じ名前空間の子要素

foreach ($xml as $item) {
    var_dump($item);
}

※ 反復処理する値にテキストノードや名前空間の違う要素は含まれません。

$xmlString = '<root xmlns:n="https://example.com/n">
    <a>1</a><a>2</a><a>3</a>
    <n:a>4</n:a>
    <b>5</b>
    6
</root>';
$xml = simplexml_load_string($xmlString);
foreach ($xml as $child) {
    var_dump($child); // <a>1</a>, <a>2</a>, <a>3</a>, <b>5</b> のみ foreach の対象になる
}

指定した名前空間の子要素

children() で名前空間を指定できます。(children('名前空間接頭辞', true) または children('名前空間URI'))

$xmlString = '<root xmlns:n="https://example.com/n">
    <a>1</a><a>2</a><a>3</a>
    <n:a>4</n:a>
    <b>5</b>
</root>';
$xml = simplexml_load_string($xmlString);
foreach ($xml->children('n', true) as $child) {
    var_dump($child);
}

すべての子要素

xpath('*') などですべての子要素を指定できます。

$xmlString = '<root xmlns:n="https://example.com/n">
    <a>1</a><a>2</a><a>3</a>
    <n:a>4</n:a>
    <b>5</b>
</root>';
$xml = simplexml_load_string($xmlString);
foreach ($xml->xpath('*') as $child) {
    var_dump($child);
}

XPath 検索

$result = $xml->xpath('item/url'); // 各 <item> の子要素の <url>
foreach ($result as $url) {
    var_dump($url);
}

※ 要素を返す用途以外の XPath は評価できません。(count(*) など)

SimpleXMLElement を DOM (DOMElement) に変換

$domItem = dom_import_simplexml($item);

連想配列に変換

簡易的な変換

$arr = json_decode(json_encode($xml), true);

※ 要素と並列しているテキストノードや名前空間の違う要素は含まれません。

$xmlString = '<root xmlns:n="https://example.com/n">
    <a>1</a><a>2</a><a>3</a>
    <n:a>4</n:a>
    <b>5</b>
    6
</root>';
$xml = simplexml_load_string($xmlString);
$arr = json_decode(json_encode($xml), true);
print_r($arr);
/*
Array
(
    [a] => Array
        (
            [0] => 1
            [1] => 2
            [2] => 3
        )

    [b] => 5
)
*/

補足

SimpleXML は取得したい要素がいくつのときでも透過的に対応できるため、わざわざ連想配列に変換しなくてもいいかもしれません。

対象要素が1つの場合
$xmlString = '<root><a>1</a></root>';

$xml = simplexml_load_string($xmlString);
$a = (string)$xml->a; // -> 1

$arr = json_decode(json_encode($xml), true);
$a = $arr['a']; // -> 1;
対象要素が無い場合 (SimpleXML だと空文字列、array だとそのまま取得しようとすると Notice エラー)
$xmlString = '<root></root>';

$xml = simplexml_load_string($xmlString);
$a = (string)$xml->a;// -> 空文字列

$arr = json_decode(json_encode($xml), true);
//$a = $arr['a']; // -> Notice: Undefined Index: a
$a = $arr['a'] ?? '';
対象要素が複数ある場合 (SimpleXML だと最初の要素の文字列を取得, array だと配列)
$xmlString = '<root><a>1</a><a>2</a><a>3</a></root>';

$xml = simplexml_load_string($xmlString);
$a = (string)$xml->a; // -> 1

$arr = json_decode(json_encode($xml), true);
$a = $arr['a']; // -> array(1, 2, 3);