10
11

More than 5 years have passed since last update.

SimpleXMLの名前空間・CDATAセクション・整形出力

Posted at

基本

名前空間

例($data)
<?xml version="1.0"?>
<root xmlns:qiita="http://www.w3.org/2001/XMLSchema-instance">
  <qiita:a>foo</qiita:a>
  <b qiita:c="bar" />
</root>

名前空間つき要素

読み出し
$xml = new SimpleXMLElement($data);
var_dump((string)$xml->children('qiita', true)->a); // string(3) "foo"
書き込み
$xml = new SimpleXMLElement($data);
$xml->addChild('d', 'baz', 'qiita');
$data = $xml->asXML(); // <qiita:d>baz</qiita:d> が追加される

名前空間つき属性

読み出し
$xml = new SimpleXMLElement($data);
var_dump((string)$xml->b->attributes('qiita', true)['c']); // string(3) "bar"
書き込み
$xml = new SimpleXMLElement($data);
$xml->addChild('d')->addAttribute('xmlns:qiita:e', 'qux');
$data = $xml->asXML(); // <d qiita:e="qux" /> が追加される

CDATAセクション

例($data)
<?xml version="1.0"?>
<root xmlns:qiita="http://www.w3.org/2001/XMLSchema-instance">
  <a><![CDATA[foo<br />bar]]></a>
</root>
読み出し
$xml = new SimpleXMLElement($data, LIBXML_NOCDATA);
var_dump((string)$xml->a); // string(12) "foo<br />bar"
書き込み
出来ません

整形出力

出来ません

継承クラスの実装

素の SimpleXMLElement では実現できなかったものを SimpleXMLElement2 として継承実装してみます。

クラス定義
<?php

class SimpleXMLElement2 extends \SimpleXMLElement {

    /**
     * CDATAセクションを自身の内部に生成
     * 
     * @param string $data
     * @return SimpleXMElement2 $this
     */
    public function setCData($data) {
        $dom = dom_import_simplexml($this);
        $dom->appendChild($dom->ownerDocument->createCDATASection($data));
        return $this;
    }

    /**
     * CDATAセクションを新しい要素の中に生成
     * 
     * @param string $name
     * @param string $data
     * @param string [$namespace]
     * @return SimpleXMElement2 新しい要素
     */
    public function addChildWithCData($name, $data, $namespace = null) {
        $child = $this->addChild($name, null, $namespace);
        $dom = dom_import_simplexml($child);
        $dom->appendChild($dom->ownerDocument->createCDATASection($data));
        return $child;
    }

    /**
     * XMLを整形して出力
     * 
     * @param string [$filename]
     * @return mixed ファイル名を省略したときは文字列、指定したときは書き込み結果
     */
    public function asPrettyXML($filename = null) {
        $dom = dom_import_simplexml($this);
        $dom->ownerDocument->formatOutput = true;
        $data = $dom->ownerDocument->saveXML(
            $dom->ownerDocument !== $dom->parentNode ? $dom : null
        );
        return $filename !== null ? (bool)file_put_contents($filename, $data) : $data;
    }

}
使用例(コード)
$url  = 'http://www.w3.org/2001/XMLSchema-instance';
$data = 'foo<br />bar';
$out  = 'php://output';

$xml = new SimpleXMLElement2('<root xmlns:qiita="' . $url .'" />');
$xml->addChild('a')->setCData($data);
$xml->addChildWithCData('b', $data);
$xml->addChild('c', null, $url)->setCData($data);
$d = $xml->addChildWithCData('d', $data, $url);

echo 'FULL(Normal)' . PHP_EOL;
$xml->asXML($out);
echo PHP_EOL;

echo 'FULL(Pretty)' . PHP_EOL;
$xml->asPrettyXML($out);
echo PHP_EOL;

echo 'D(Normal)' . PHP_EOL;
$d->asXML($out);
echo PHP_EOL, PHP_EOL;

echo 'D(Pretty)' . PHP_EOL;
$d->asPrettyXML($out);
echo PHP_EOL;
使用例(実行結果)
FULL(Normal)
<?xml version="1.0"?>
<root xmlns:qiita="http://www.w3.org/2001/XMLSchema-instance"><a><![CDATA[foo<br />bar]]></a><b><![CDATA[foo<br />bar]]></b><qiita:c><![CDATA[foo<br />bar]]></qiita:c><qiita:d><![CDATA[foo<br />bar]]></qiita:d></root>

FULL(Pretty)
<?xml version="1.0"?>
<root xmlns:qiita="http://www.w3.org/2001/XMLSchema-instance">
  <a><![CDATA[foo<br />bar]]></a>
  <b><![CDATA[foo<br />bar]]></b>
  <qiita:c><![CDATA[foo<br />bar]]></qiita:c>
  <qiita:d><![CDATA[foo<br />bar]]></qiita:d>
</root>

D(Normal)
<qiita:d><![CDATA[foo<br />bar]]></qiita:d>

D(Pretty)
<qiita:d><![CDATA[foo<br />bar]]></qiita:d>
10
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
11