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

# 基本

## 名前空間

```xml:例($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>
```

### 名前空間つき要素

```php:読み出し
$xml = new SimpleXMLElement($data);
var_dump((string)$xml->children('qiita', true)->a); // string(3) "foo"
```

```php:書き込み
$xml = new SimpleXMLElement($data);
$xml->addChild('d', 'baz', 'qiita');
$data = $xml->asXML(); // <qiita:d>baz</qiita:d> が追加される
```

### 名前空間つき属性

```php:読み出し
$xml = new SimpleXMLElement($data);
var_dump((string)$xml->b->attributes('qiita', true)['c']); // string(3) "bar"
```

```php:書き込み
$xml = new SimpleXMLElement($data);
$xml->addChild('d')->addAttribute('xmlns:qiita:e', 'qux');
$data = $xml->asXML(); // <d qiita:e="qux" /> が追加される
```

## CDATAセクション

```xml:例($data)
<?xml version="1.0"?>
<root xmlns:qiita="http://www.w3.org/2001/XMLSchema-instance">
  <a><![CDATA[foo<br />bar]]></a>
</root>
```

```php:読み出し
$xml = new SimpleXMLElement($data, LIBXML_NOCDATA);
var_dump((string)$xml->a); // string(12) "foo<br />bar"
```

```php:書き込み
出来ません
```

## 整形出力

```php
出来ません
```

# 継承クラスの実装

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

```php:クラス定義
<?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;
    }
    
}
```

```php:使用例(コード)
$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;
```

```html:使用例(実行結果)
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>
```