以下のXMLを使用してサンプルコードを解説する。
<?xml version="1.0"?> <library xmlns:lib="http://sample.com/library"> <book isbn="0111222333"> <lib:title>She sells seashells</lib:title> <author>Emily</author> <publisher>store</publisher> </book> <book isbn="0123456789"> <title>Eight apes ate eight apples</title> <author>John</author> <publisher>shop</publisher> </book> <book isbn="9876543210"> <title>Strike</title> <author>Mike</author> <publisher>shop</publisher> </book> <book isbn="1234567890"> <title>Shine</title> <author>Jack</author> <publisher>store</publisher> </book> </library>
■読込
ファイルパスを指定
<?php $dom = new DomDocument(); $dom->load('test.xml'); ?>
文字列をDOMとして読込
<?php $dom = new DomDocument(); $dom->loadXML($str); ?>
HTMLファイルとして読込
<?php $dom = new DomDocument(); $dom->loadHTMLFile('test.html'); ?>
HTMLとして読込
<?php $dom = new DomDocument(); $dom->loadHTML($str); ?>
各メソッドについて
ファイルからの読込 | 文字列からの読込 | |
---|---|---|
XML | DomDocument::load | DomDocument::loadXML |
HTML | DomDocument::loadHTMLFile | DomDocument::loadHTML |
■保存
ファイルへの保存
<?php $dom = new DomDocument(); $dom->load('test.xml'); if($is_xhtml){ $dom->save('test.xml'); } else{ $dom->saveHTMLFile('test.html'); } ?>
データとして格納
<?php $dom = new DomDocument(); $dom->load('test.xml'); if($is_xhtml){ $data = $dom->saveXML(); } else{ $data = $dom->saveHTML(); } ?>
各メソッドについて
ファイルに保存 | データとして返す | |
---|---|---|
XML | DomDocument::save | DomDocument::saveXML |
HTML | DomDocument::saveHTMLFile | DomDocument::saveHTML |
■DOMにおけるXPath
以下のようにDomXPathオブジェクトを通して、DomDocumentオブジェクトに対するxpathを実行する。
<?php $dom = new DomDocument(); $dom->load('test.xml'); $xpath = new DomXPath($dom); $result = $xpath->query('/library/book/title/text()'); foreach($result as $title){ print($title->data); } /* Eight apes ate eight apples Strike Shine */ ?>
以下のように、名前空間を使うこともできる。
<?php $dom = new DomDocument(); $dom->load('test.xml'); $xpath = new DomXPath($dom); $xpath->registerNamespace('lib', 'http://sample.com/library'); $result = $xpath->query('//lib:title/text()'); foreach($result as $book){ print($book->data); } /* She sells seashells */ ?>
■XMLドキュメントの操作
以下のようにして、要素を追加することができる。documentElementはドキュメントのルートの要素を示す。
<?php $dom = new DomDocument(); $dom->load('test.xml'); $book = $dom->createElement('book'); $book->setAttribute('isbn', '0123456789'); $title = $dom->createElement('title'); $txt = $dom->createTextNode('PHP'); $title->appendChild($txt); $book->appendChild($title); $author = $dom->createElement('author', 'Jane'); $book->appendChild($author); $publisher = $dom->createElement('publisher', 'amazon'); $book->appendChild($publisher); $dom->documentElement->appendChild($book); /* <?xml version="1.0" encoding="utf-8"?> <library> <book isbn="0111222333"> <title>She sells seashells</title> <author>Emily</author> <publisher>store</publisher> </book> <book isbn="0123456789"> <title>Eight apes ate eight apples</title> <author>John</author> <publisher>shop</publisher> </book> <book isbn="9876543210"> <title>Strike</title> <author>Mike</author> <publisher>shop</publisher> </book> <book isbn="1234567890"> <title>Shine</title> <author>Jack</author> <publisher>store</publisher> </book> <book isbn="0123456789"><title>PHP</title><author>Jane</author><publisher>amazon</publisher></book></library> */ ?>
各メソッドについて
- DomElement DomDocument::createElement(string $name[, string $value])
- 新しい要素ノードを生成する。第二引数で要素の値を指定することもできる
- DomAttr DomElement::setAttribute(string $name, string $value)
- 新しい属性を追加する
- DomNode DomNode::appendChild(DomNode $node)
- 子要素を追加する
- DomText DomNode::createTextNode(string $content)
- 新しいテキストノードを生成する
個人的にこのあたりはJavaScriptで馴染んでいるので覚えやすい。
■要素の移動
特定の要素の前に移動する場合は、以下のようにDomNode::insertBeforeメソッドを使用する。
<?php $dom = new DomDocument(); $dom->load('test.xml'); $xpath = new DomXPath($dom); $result = $xpath->query('/library/book'); $xpath->item(1)->paentNode->insertBefore($result->item(1), $result->item(0)); print($dom->saveXML()); /* <?xml version="1.0" encoding="utf-8"?> <library> <book isbn="0123456789"> <title>Eight apes ate eight apples</title> <author>John</author> <publisher>shop</publisher> </book> <book isbn="0111222333"> <title>She sells seashells</title> <author>Emily</author> <publisher>store</publisher> </book> <book isbn="9876543210"> <title>Strike</title> <author>Mike</author> <publisher>shop</publisher> </book> <book isbn="1234567890"> <title>Shine</title> <author>Jack</author> <publisher>store</publisher> </book> </library> */ ?>
要素の最後尾に移動する場合は、以下のようにDomNode::appendChildメソッドを使用する。
<?php $dom = new DomDocument(); $dom->load('test.xml'); $xpath = new DomXPath($dom); $result = $xpath->query('/library/book'); $result->item(1)->parentNode->appendChild($result->item(0)); print($dom->saveXML()); /* <?xml version="1.0" encoding="utf-8"?> <library> <book isbn="0123456789"> <title>Eight apes ate eight apples</title> <author>John</author> <publisher>shop</publisher> </book> <book isbn="9876543210"> <title>Strike</title> <author>Mike</author> <publisher>shop</publisher> </book> <book isbn="1234567890"> <title>Shine</title> <author>Jack</author> <publisher>store</publisher> </book> <book isbn="0111222333"> <title>She sells seashells</title> <author>Emily</author> <publisher>store</publisher> </book> </library> */ ?>
但し、上述のメソッドはノードをコピーしない。従って、複製を挿入したい場合は、DomNode::cloneNodeメソッドを使用し、複製してから挿入しなければならない。
<?php $dom = new DomDocument(); $dom->load('test.xml'); $xpath = new DomXPath($dom); $result = $xpath->query('/library/book'); $elm = $result->item(0)->cloneNode(); $result->item(1)->parentNode->appendChild($elm); print($dom->saveXML()); /* <?xml version="1.0" encoding="utf-8"?> <library> <book isbn="0111222333"> <title>She sells seashells</title> <author>Emily</author> <publisher>store</publisher> </book> <book isbn="0123456789"> <title>Eight apes ate eight apples</title> <author>John</author> <publisher>shop</publisher> </book> <book isbn="9876543210"> <title>Strike</title> <author>Mike</author> <publisher>shop</publisher> </book> <book isbn="1234567890"> <title>Shine</title> <author>Jack</author> <publisher>store</publisher> </book> <book isbn="0111222333"/></library> */ ?>
各メソッドについて
- DomNode DomNode::insertBefore(DomNode $node[, DomNode $refnode])
- 第一引数で指定したノードが、第二引数で指定したノードの前に挿入される。
- DomNode DomNode::appendChild(DomNode $node)
- DomNodeの最後尾に、引数で指定したノードを挿入する。
- DomNode DomNode::cloneNode(bool $recursive=false)
- DomNodeを複製する。引数にtrueを指定すると子ノードまで含めた複製が生成される。デフォルトはfalse。
■要素の削除
要素を削除するには、以下のようにDomNode::removeChildメソッドを使用する。また、属性を削除するには、DomNode::removeAttributeメソッド使用する。さらに、要素内のテキストを削除したい場合は、DomCharacterData::deleteDataメソッドを使用する。
<?php $dom = new DomDocument(); $dom->load('test.xml'); $xpath = new DomXPath($dom); $result = $xpath->query('/library/book'); $result->item(0)->parentNode->removeChild($result->item(0)); $result->item(1)->removeAttribute('isbn'); $result = $xpath->query('/library/book/publisher/text()'); $result->item(0)->deleteData(0, $result->item(0)->length); print($dom->saveXML()); /* <?xml version="1.0" encoding="utf-8"?> <library> <book> <title>Eight apes ate eight apples</title> <author>John</author> <publisher></publisher> </book> <book isbn="9876543210"> <title>Strike</title> <author>Mike</author> <publisher>shop</publisher> </book> <book isbn="1234567890"> <title>Shine</title> <author>Jack</author> <publisher>store</publisher> </book> </library> */ ?>
各メソッドについて
- DomNode DomNode::removeChild(DomNode $node)
- DomNode内から、引数で指定したノードを削除する。
- bool DomElement::removeAttribute(string $name)
- DomNodeの、引数で指定した属性を削除する。
- void DomCharacterData::deleteData(int $offset, int $count)
- DomCharacterDataを対象として、第一引数で指定したオフセット値から、第二引数で指定した文字数分削除する。
■DOMにおける名前空間の扱い方
以下のように、要素や属性に名前空間を指定した記述をした後で、名前空間とそのURIを示す属性を要素に追加することで、名前空間を扱うことができる。
<?php $dom = new DomDocument(); $node = $dom->createElement('ns1:somenode'); $node->setAttribute('ns2:someattribute', 'somevalue'); $node2 = $dom->createElement('ns3:anothernode'); $node->appendChild($node2); $node->setAttribute('xmlns:ns1', 'http://sample.org/ns1'); $node->setAttribute('xmlns:ns2', 'http://sample.org/ns2'); $node->setAttribute('xmlns:ns3', 'http://sample.org/ns3'); $dom->appendChild($node); print($dom->saveXML()); /* <?xml version="1.0"?> <ns1:somenode ns2:someattribute="somevalue" xmlns:ns1="http://sample.org/ns1" xmlns:ns2="http://sample.org/ns2" xmlns:ns3="http://sample.org/ns3"> <ns3:anothernode/> </ns1:somenode> */ ?>
但し、以下のようにDomNode::createElementNSメソッドや、DomNode::setAttributeNSを使用すると、自ノードと親ノードに名前空間とそのURIを示す属性が自動的に付加される。
<?php $dom = new DomDocument(); $node = $dom->createElementNS('http://sample.org/ns1', 'ns1:somenode'); $node->setAttributeNS('http://sample.org/ns2', 'ns2:someattribute', 'somevalue'); $node2 = $dom->createElementNS('http://sample.org/ns3', 'ns3:anothernode'); $node3 = $dom->createElementNS('http://sample.org/ns1', 'ns1:someothernode'); $node->appendChild($node2); $node->appendChild($node3); $dom->appendChild($node); print($dom->saveXML()); /* <?xml version="1.0"?> <ns1:somenode xmlns:ns1="http://sample.org/ns1" xmlns:ns2="http://sample.org/ns2" xmlns:ns3="http://sample.org/ns3" ns2:someattribute="somevalue"> <ns3:anothernode xmlns:ns3="http://sample.org/ns3"/> <ns1:someothernode/> </ns1:somenode> */ ?>
出力されるXMLは若干違うものの、後者のコードの方が短くシンプルにはなる。
■SimpleXMLとの相互変換
SimpleXMLからDOMへの変換
以下のように、dom_import_simplexml関数を使用してSimpleXMLからDOMへ変換が行える。
<?php $xml = new SimpleXMLElement('test.xml', null, true); $node = dom_import_simplexml($xml); $dom = new DomDocument(); $dom->importNode($node, true); $dom->appendChild($node); print($dom->saveXML()); ?>
DOMからSimpleXMLへの変換
以下のように、simplexml_import_dom関数を使用してDOMからSimpleXMLへ変換が行える。
<?php $dom = new DomDocument(); $dom->load('test.xml'); $xml = simplexml_import_dom($dom); print($xml->asXML()); ?>