[PHP] SimpleXML の asXML をフォーマットして出力する
SimpleXML シリーズの第3段です。 mopi フレームワーク で SimpleXML を多用しています。概ね問題ないのですが、いくつか気になるところがあって、ちょっと扱いに困るのが PHP 内部で addChild しながら XML を作っていくと、asXML したときに折り返しやらインデントされない状態(下手したら横一直線)で出力されることです。 アプリケーションが触る分には折り返されてなかろうがインデントされてなかろうが書式が正しければ問題ないんですが、作った XML ファイルを人が見て確認する必要がある場合には、どうしてもその際にフォーマットしてやる後手間が発生します。 もちろん、専用のXMLリーダーなりを使えばいいんですけど、なんだかんだで結局テキストエディタなどで開くことが多くて、横一直線のXMLファイルだったりするとかなり残念な気持ちになります。 なので、また自作してみました。(DomElement に置き換えて出力って手もあるんですが、今回は自分でフォーマットです。)
■ サンプルコード:SimpleXML の Formatoutput
class Mopi_Simple_Xml extends SimpleXMLElement { public function asXML ($filePath = null, $formatOutput = true) { if (!$formatOutput) { return parent::asXML($filePath); } else { $string = $this->_format(parent::asXML()); if ($filePath) { file_put_contents($filePath, $string); } return $string; } } private function _format ($string) { $string = rtrim($string); $string = preg_replace("/>\s*</", ">\n<", $string); $lines = explode("\n", $string); $returnLines = array(); $indent = 0; foreach ($lines as $line) { if (preg_match('/^<[^\/\!][^<]+[^\/|\?]>$/', $line)) { $type = 'increment'; } elseif (preg_match('/^<\/[^<]+>$/', $line)) { $type = 'decrement'; } else { $type = 'none'; } if ($type == 'decrement') { $indent--; } $returnLines[] = str_repeat("\t", $indent) . $line . "\n"; if ($type == 'increment') { $indent++; } } return implode('', $returnLines); } }
■ 利用例
// 検証用オブジェクトの作成(普通の SimpleXML) $xml01 = simplexml_load_string('<?xml version="1.0" encoding="UTF-8"?><root><child id="1" name="C太郎" power="100" /><child id="3" name="B太郎" power="100" /><child id="4" name="D太郎" power="20" /><child id="2" name="A太郎" power="10" /></root>'); // 検証用オブジェクトの作成(第二引数で今回作成したクラスを指定) $xml02 = simplexml_load_string('<?xml version="1.0" encoding="UTF-8"?><root><child id="1" name="C太郎" power="100" /><child id="3" name="B太郎" power="100" /><child id="4" name="D太郎" power="20" /><child id="2" name="A太郎" power="10" /></root>', 'Mopi_Simple_Xml'); //普通の SimpleXML を asXML var_dump($xml01->asXML()); //今回作成した SimpleXML を asXML var_dump($xml02->asXML());
■ 結果
string(219) "<?xml version="1.0" encoding="UTF-8"?> <root><child id="1" name="C太郎" power="100"/><child id="3" name="B太郎" power="100"/><child id="4" name="D太郎" power="20"/><child id="2" name="A太郎" power="10"/></root> " string(228) "<?xml version="1.0" encoding="UTF-8"?> <root> <child id="1" name="C太郎" power="100"/> <child id="3" name="B太郎" power="100"/> <child id="4" name="D太郎" power="20"/> <child id="2" name="A太郎" power="10"/> </root>
まだ、こちらはあまり実践投入されてないので、細かい動作でもう少し検証がいるように思います。 改良したらまたお知らせするかもしれません。











