SimpleXML
介紹
SimpleXML提供了一種簡單,直觀的方法來處理XML。它只有一個單一類型的類,三個函數和六個方法。
使用SimpleXML
SimpleXMLElement
類是這個擴展中所有操作的核心類。可以用new關鍵字直接創建這種類,或是使用simplexml_load_file()或
simplexml_load_string()函數返回這種類。本文將使用清單7-1的XML文檔來說明如何使用SimpleXML,將此文檔命名爲
sml.xml。
清單7-1 sml.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
<book lang="en">
<bookinfo>
<title>SimpleXML in PHP 5</title>
<author>
<firstname>Rob</firstname>
<surname>Richards</surname>
</author>
<copyright>
<year>2005</year>
<holder>Rob Richards</holder>
</copyright>
</bookinfo>
<preface>
<title>Using SimpleXML</title>
<para>An example DOM Tree using DocBook.</para>
</preface>
<chapter id="navigation">
<title>Accessing Elements</title>
<para>Elements are accessed as properties</para>
<para>
<![CDATA[
<?php
$data = '<?xml version="1.0"?>
<root>content</root>';
$sxe = simplexml_load_string($data);
var_dump($sxe);
?>
]]>
</para>
</chapter>
</book>
創建一個SimpleXMLElement對象
使用new關鍵字創建
$xml = "<root><node1>Content</node1></root>";
$sxe = new SimpleXMLElement($xml);//SimpleXMLElement Object ( [node1] => Content )
使用simplexml_load_string()創建
$xml = "<root><node1>Content</node1></root>";
$sxe = simplexml_load_string($xml);//SimpleXMLElement Object ( [node1] => Content )
如何選擇這兩種創建SimpleXMLElement的方法呢?simplexml_load_string()提供了更多的函數,比如控制解析選項的能力。如果不需要這些額外的函數的話就可以憑個人愛好選擇一種方法。
使用simplexml_load_file()從一個URI創建
$sxe = simplexml_load_file("filename.xml");
simplexml_load_string()和simplexml_load_file()都有一個必需的參數和可選的參數。從PHP5.1開始simplexml_load_file()多了一個用來控制解析行爲的第三個參數。
/* Prototype for PHP 5.0 */
simplexml_load_file(string data [, string class_name])
/* Prototype for PHP 5.1 */
simplexml_load_file(string data [, string class_name [, int options]])
保存XML數據
與DOM擴展一樣,SimpleXML也提供了一個用來輸出XML內容的方法asXML()。可以用這個方法以字符串或文件形式輸出這個文檔或文檔中的某個節點。
$xml = "<root><node1>content</node1></root>";
$sxe = new SimpleXMLElement($xml);
print $sxe->asXML();
$sxe->asXML('test.xml');
輸出:
<?xml version="1.0"?>
<root><node1>content</node1></root>
訪問元素節點
在SimpleXML中,可以直接通過元素的名稱來訪問特定的元素。
訪問元素
當一個文檔被載入SimpleXML時,文檔被看成是一個SimpleXML對象,文檔中的所有元素都被看成是該對象的屬性。
<?php
$book = simplexml_load_file('sxml.xml');
/* Access the bookinfo child element of the book element */
$bookinfo = $book->bookinfo;
/* Access the title child element from the bookinfo element */
$title = $bookinfo->title;
?>
如果使用DOM來訪問title,代碼如下
$dom = new DOMDocument();
$dom->load('sxml.xml');
$book = $dom->documentElement;
foreach($book->childNodes as $node) {
if ($node->nodeName == "bookinfo") {
foreach($node->childNodes as $child) {
if ($child->nodeName == "title") {
$node = $child;
break 2;
}
}
}
}
if ($node) {
$title = $node;
}
顯然SimpleXML對的起它的名字。
訪問內容
<?php
$book = simplexml_load_file('sxml.xml');
$bookinfo = $book->bookinfo;
$title = $bookinfo->title;
/* Object examined with var_dump */
var_dump($title);
/* Using print with element containing text-only content */
print "Title: ".$title."/n";
$author = $bookinfo->author;
/* Object examined with var_dump */
var_dump($author);
/* Using print with element containing child elements */
print "Author: ".$author."/n";
?>
這段代碼檢查了兩個SimpleXMLElement對象,$author和$title。兩者的區別是$author元素有包含子元素而$title元素只包含一個文本節點。
輸出如下:
object(SimpleXMLElement)#4 (1) {
[0]=>
string(18) “SimpleXML in PHP 5″
}
Title: SimpleXML in PHP 5
object(SimpleXMLElement)#6 (2) {
[”firstname”]=>
string(3) “Rob”
[”surname”]=>
string(8) “Richards”
}
Author:
檢查輸出結果可以發現,$title是一個包含有文本內容的SimpleXMLElement對象,索引0表示元素的文本內容,當打印$title時,文本內容將以字符串形式返回。
$author元素有兩個子元素,從輸出結果可以看出,這些子元素被看成SimpleXMLElement對象的屬性,這些屬性的值是它們對應的節點包含的內容。用print輸出$author時,輸出結果是空格和換行符。
如果一個元素無子元素,只包含文本內容,那麼可以將此元素所對應的SimpleXMLElement對象視爲一個字符串來使用,有些情況下,爲了獲得以字符串形式返回文本內容,必須執行類型轉換操作:
$titlecontent = (string) $title;
有 子元素的元素所對應的SimpleXMLElement對象將返回該對象直屬的文本節點,而不是任一子元素的內容。如果用print輸出$author, 將得到一個27字符長度,包含空格和換行符的字符。 Neither of the child elements,firstname or surname, nor their content is returned in the string.
爲了理解最後一點,可以運行一些下面這段代碼:
$doc = new SimpleXMLElement('<root>some<child1>subtext</child1>thing</root>');
print $doc;
使用迭代對象
SimpleXMLElement 對象在大多數情況下是可迭代的,可以用這個特性來訪問文檔中多個元素名一樣的節點,如清單7-1中的para元素。在使用元素名作爲屬性來訪問一個元素 時,SimpleXMLElement對象不是一個單一節點的存取器,它實際上是作爲屬性訪問的元素名節點的集合。直接利用元素名作爲屬性訪問實際上訪問 訪問這個集合中的第一個元素。
看下這段代碼
$book = simplexml_load_file('sxml.xml');
$para = $book->chapter->para;
print $para."/n";
foreach($para AS $node) {
print $node."/n";
}
這 段代碼中,$para變量就是para元素的集合,實際上包含了兩個元素。如果直接訪問$para的話實際上是訪問第一個para元素,利用迭代可以看出 $para所包含的內容是兩個元素。其中CDATA節點被看做是純文本的內容,其中包含的空格和換行符都會被如實輸出。
用迭代的方式來訪問所有的元素顯然不太實際,有時候我們希望訪問結果集中的某個特定的元素,這時可以使用從0開始的索引來訪問這個結果集,例如:
$book = simplexml_load_file('sxml.xml');
$para = $book->chapter->para[1];
print "Content: ".$para."/n";
foreach($para AS $node) {
print "Iter Content: ".$node."/n";
}
運行這段代碼會發現foreach循環失效了,這是因爲SimpleXML知道你只是在尋找結果集中某個特定的元素,這種情況下對象是不可迭代的。
Caution:使用索引方式訪問一個SimpleXMLElement對象會返回一個不可以迭代的對象,因爲它是一個單一的元素而不是一個元素集。
訪問未知元素
在不知道XML文檔的結構的情況下可以利用SimpleXML中的children()方法來返回一個可以迭代方式訪問的某個元素的所有子元素的SimpleXML對象。如:
$book = simplexml_load_file('sxml.xml');
$author = $book->bookinfo->author;
$children = $author->children();
foreach($children AS $child) {
print $child."/n";
}
上述代碼用children()方法返回了author節點下的所有子元素,然後用foreach循環輸出。也可以使用索引方式訪問返回的子元素,如echo $children[1];。
理解PHP對象函數
SimpleXMLElement對象的屬性是動態的,因爲這些屬性是由對象實例決定的,而不是由類本身決定的。在PHP中,可以利用get_object_vars()函數來返回某個對象的所有屬性,返回的結果是一個包含屬性和值的數組,如:
$props = get_object_vars($author);
foreach ($props AS $name=>$value) {
print $name.": ".$value."/n";
}
輸出:
firstname: Rob
surname: Richards
這段代碼訪問的子元素都只包含文本內容,所以返回的數組只包含屬性名和值,對於一個包含許多子節點的元素,返回的結果稍微複雜點:
$props = get_object_vars($book->bookinfo);
var_dump($props);
輸出:
array(3) {
[”title”]=>
string(18) “SimpleXML in PHP 5″
[”author”]=>
object(SimpleXMLElement)#4 (2) {
[”firstname”]=>
string(3) “Rob”
[”surname”]=>
string(8) “Richards”
}
[”copyright”]=>
object(SimpleXMLElement)#5 (2) {
[”year”]=>
string(4) “2005″
[”holder”]=>
string(12) “Rob Richards”
}
}
使用DOM互操作
另一種訪問未知元素的方法是使用DOM,可以將一個節點導入DOM擴展,然後使用DOM的屬性和方法來處理。
$book = simplexml_load_file('sxml.xml');
$author = $book->bookinfo->author;
$children = $author->children();
foreach($children AS $child) {
/* Import node into DOM, and get nodeName */
$element = dom_import_simplexml($child);
$name = $element->nodeName;
print $name.": ".$child."/n";
}
將節點導入DOM擴展時並沒有創建一個節點的副本(copy),而是直接訪問導入的節點(JIMMY注:這個概念很重要)。
本文轉載於http://blog.csdn.net/guoguo1980/article/details/2436318