详解PHP使用DOMDocument解析XML

最近在学习PHP时候,想实现PHP使用Socket访问Linux服务端程序,结果实现了之后,又遇到了问题,和Linux服务端通信使用的是XML报文。PHP如何解析XML报文呢。网罗了很多方法,最终测试发现还是DOMDocument很好用,本文结合自己的实际经验记录下如何使用DOMDocument解析XML报文的。

Dom(Document object model)文档-对象-模型,核心思想是把一个XML文件看成一个对象模型,然后通过对象的方式来操作XML文件。我们先总结出DOM对象的属性方法,在分别用案例说明其应用!

DOMDocument *属性:*

Attributes存储节点的属性列表(只读)

childNodes存储节点的子节点列表(只读)

dataType返回此节点的数据类型

Definition以DTD或XML模式给出的节点的定义(只读)

Doctype指定文档类型节点(只读)

documentElement返回文档的根元素(可读写)

firstChild返回当前节点的第一个子节点(只读)

Implementation返回XMLDOMImplementation对象

lastChild返回当前节点最后一个子节点(只读)

nextSibling返回当前节点的下一个兄弟节点(只读)

nodeName返回节点的名字(只读)

nodeType返回节点的类型(只读)

nodeTypedValue存储节点值(可读写)

nodeValue返回节点的文本(可读写)

ownerDocument返回包含此节点的根文档(只读)

parentNode返回父节点(只读)

Parsed返回此节点及其子节点是否已经被解析(只读)

Prefix返回名称空间前缀(只读)

preserveWhiteSpace指定是否保留空白(可读写)

previousSibling返回此节点的前一个兄弟节点(只读)

Text返回此节点及其后代的文本内容(可读写)

url返回最近载入的XML文档的URL(只读)

Xml返回节点及其后代的XML表示(只读)

DOMDocument *方法:*

appendChild为当前节点添加一个新的子节点,放在最后的子节点后

cloneNode返回当前节点的拷贝

createAttribute创建新的属性

createCDATASection创建包括给定数据的CDATA段

createComment创建一个注释节点

createDocumentFragment创建DocumentFragment对象

createElement_x创建一个元素节点

createEntityReference创建EntityReference对象

createNode创建给定类型,名字和命名空间的节点

createPorcessingInstruction创建操作指令节点

createTextNode创建包括给定数据的文本节点

getElementsByTagName返回指定名字的元素集合

hasChildNodes返回当前节点是否有子节点

insertBefore在指定节点前插入子节点

Load导入指定位置的XML文档

loadXML导入指定字符串的XML文档

removeChild从子结点列表中删除指定的子节点

replaceChild从子节点列表中替换指定的子节点

Save把XML文件存到指定节点

selectNodes对节点进行指定的匹配,并返回匹配节点列表

selectSingleNode对节点进行指定的匹配,并返回第一个匹配节点

transformNode使用指定的样式表对节点及其后代进行转换

一、创建一个XML文件

createElement("class"); $dom->appendChild($root); $dom->save("test.xml"); } else{ $dom->load("test.xml"); } print $dom->saveXML(); ?>

 二、XML节点的创建、插入、删除、替换、修改

1、创建节点元素

有两种方法可以用来创建元素:

一是使用DOMDocument对象中createElement()和createElementNS()方法;

二是利用DOMElement直接实例化一个DOMElement对象。

创建一个bookinfo元素

$bookinfo = $dom->createElement("bookinfo");

这段代码返回了一个名为”bookinfo”的DOMElement对象类型元素给$bookinfo变量。

也可以创建一个包含内容的元素

$bititle = $dom->createElement("title", "DOM in PHP 5");

虽然已经创建了两个元素,但是它们跟文档没有直接关系,是独立的两个元素。

创建一个带有命名空间的元素

$biauthor = $dom->createElementNS(NULL, "author"); $trash = $dom->createElementNS("http://www.example.com/trash", "tr:trash");

直接实例化DOMElement对象来创建元素

$firstname = new DOMElement("firstname", "Rob"); $surname = new DOMElement("surname", "Richards"); $nsElement = new DOMElement("nse:myelement", NULL, "http://www.example.com/ns");

第三行代码的NULL说明不指定值给所创建的元素。

2、插入节点元素

插入元素节点的方法是从DOMNode类继承的,它们不仅可以用于元素节点,还可以用于其它类型的节点。

$dom->documentElement->appendChild($bookinfo);

appendChild()方法有一个被用来指定为子节点的对象作参数,并返回所创建的节点。新插入的节点作为当前节点的最后一个子节点插入。

在插入author元素前可以先在author元素中插入firstname和surname节点。当将author节点插入文档树中时,firstname和surname也被插入文档中:

$biauthor->appendChild($surname); $biauthor->insertBefore($firstname, $surname);

上面的代码也可以这么写

$biauthor->appendChild($firstname); $biauthor->appendChild($surname);

然后将author插入bookinfo节点:

$bookinfo->appendChild($biauthor);

3、删除节点元素

首先是加载一个XML字符串:

$doc = DOMDocument::loadXML(' child1 content child2 content child3 content ');

接着要把child2元素删除,并把child3元素用newchild元素替代。

第一步是取得这些元素:

$root = $doc->documentElement; $child2 = $root->getElementsByTagName("child2")->item(0); $child3 = $root->getElementsByTagName("child3")->item(0);

接着删除$child2对象:

$root->removeChild($child2);

这时,XML文档变成如下的结构:

child1 content child3 content 在文档中会留出原来元素所占用的行。那一行空白也是一个节点,可以用下面的代码删除: $children = $root->childNodes; for ($x=$children->length; $x--; $x>=0) { $node = $children->item($x); if ($node->nodeType == XML_TEXT_NODE && $node-> isElementContentWhitespace()) { $root->removeChild($node); } } ### 4、替代节点元素 接着创建一个newchild元素来替代child3。 $oldchild = $root->replaceChild(new DOMElement("newchild", "new content"), $child3); 这时,XML文档变成如下结构: child1 content new content ### 4、修改节点元素 如果要修改节点newchild的内容: $newchild = $root->getElementsByTagName("newchild")->item(0); $newchild->nodeValue = "student"; $docXML = $doc->saveXML(); 这时,XML文档变为如下结构: child1 content student ## 三、遍历解析XML 解析XML文档或者XML字符串的时候,我们的核心思想是想获取某一节点的所有内容。 ### 访问特定节点 如果要访问特点节点可以使用节点的标签名。可使用的方法有`getElementsByTagName()`和`getElementsByTagNameNS()`,被访问的节点只能包含在文档节点(document node)和元素节点(element node)中,也就是说,要访问的节点必须是基于DOMDocument或DOMElement类。 load("post.xml"); // 获取所有的post标签 $postDom = $xml->getElementsByTagName("post"); // 循环遍历post标签 foreach($postDom as $post){ // 获取Title标签Node $title = $post->getElementsByTagName("title"); /** * 要获取Title标签的Id属性要分两步 * 1. 获取title中所有属性的列表也就是$title->item(0)->attributes * 2. 获取title中id的属性,因为其在第一位所以用item(0) * * 小提示: * 若取属性的值可以用item(*)->nodeValue * 若取属性的标签可以用item(*)->nodeName * 若取属性的类型可以用item(*)->nodeType */ echo "Id: " . $title->item(0)->attributes->item(0)->nodeValue . "
"; echo "Title: " . $title->item(0)->nodeValue . "
"; echo "Details: " . $post->getElementsByTagName("details")->item(0)->nodeValue . "

"; } ?>

以上代码中解释了如何过去“post”标签的所有内容,并且如何获取“post”标签中“title”元素的标签、类型、值三个字段。那么XML文档或者字符串就全部解析出来了。

总结,DOMDucument是个强大的工具,用它几乎能完成所有有关XML文档的操作,有一些方法还没有用到。还需要继续探究。

comments powered by Disqus