修改內容
利用SimpleXML修改元素內容非常方便,你可以改變或移除樹中的某個元素,但是不能直接在樹中添加一個元素。要添加一個元素,可以使用DOM的互操作性:
$xml = "<root><node1>content</node1></root>";
$sxe = new SimpleXMLElement($xml);
$dom = dom_import_simplexml($sxe);
$dom->appendChild(new DOMElement("node2", "content2"));
print $sxe->asXML();
輸出:
<?xml version="1.0"?>
<root><node1>content</node1><node2>content2</node2></root>
編輯文本內容
可以利用SimpleXML的屬性賦值方法來直接編輯一個元素的內容,要主意的是如果文檔中有多個元素名一樣的元素,如果沒有使用索引來指定要編輯哪個元素時PHP將發出一個警告。如:
$book = simplexml_load_file('sxml.xml');
/* Modify an unspecified para element where multiple para elements exist */
$book->chapter->para = "Removed CDATA";
輸出:
Warning: main() [/phpmanual/function.main.html]: Cannot assign to an array of nodes
(duplicate subnodes or attr detected)
必須給para指定索引告訴程序你要編輯哪個元素:
$book = simplexml_load_file('sxml.xml');
$book->chapter->para[1] = "Removed CDATA";
print $book->chapter->asXML();
輸出:
<chapter id="navigation">
<title>Acessing Elements</title>
<para>Elements are accessed as properties</para>
<para>Removed CDATA</para>
</chapter>
這樣,第二個para元素的內容被改爲Removed CDATA。如果要編輯一個在文檔中唯一存在的元素可不必指定索引,直接修改。如修改title:
$book = simplexml_load_file('sxml.xml');
$book->chapter->title = "New Title";
$book->chapter->para[1] = "Removed CDATA";
print $book->chapter->asXML();
輸出:
<chapter id="navigation">
<title>New Title</title>
<para>Elements are accessed as properties</para>
<para>Removed CDATA</para>
</chapter>
強烈建議使用索引來編輯元素,除非你對文檔的結果非常確定。使用索引來編輯title元素會比較安全,如$book->chapter->title[0] = “New Title”;這行代碼用索引[0]指定要編輯第一個title。
編輯有子樹的元素
$book = simplexml_load_file('sxml.xml');
$cholder = $book->bookinfo->copyright->holder;
print $cholder->asXML()."/n";
$book->bookinfo = "No Book Info";
print $book->bookinfo->asXML()."/n";
print $cholder->asXML()."/n";
輸出:
<holder>Rob Richards</holder>
<bookinfo>No Book Info</bookinfo>
Warning: SimpleXMLElement::asXML() [/phpmanual/function.asXML.html]: Node no
longer exists in N:/CVS Projects/php5/Debug_TS/booksxe.php on line 7
這 段代碼中,首先將文檔中的holder元素賦值給$cholder變量,然後打印該變量。bookinfo元素包含有title,author和 copyright子樹,它的內容被字符串No Book Info代替,從bookinfo的輸出結果可以看出,它的子樹被清空並且被字符串代替了。接着試圖再次打印$cholder變量的XML內容,程序輸出 一個警告,這個變量依然是一個SimpleXMLElement對象,但它所屬的節點在bookinfo元素改變時已經被破壞了。
另一種情況。將bookinfo元素中的子元素用字符串 代替。
$book = simplexml_load_file('sxml.xml');
$book->bookinfo = "<title>SimpleXML in PHP 5</title>";
print $book->bookinfo->asXML()."/n";
如果你認爲上述代碼將bookinfo中的內容清空後再給bookinfo創建了一個子節點title,那麼你錯了。輸出結果是
<title>SimpleXML in PHP 5</title>
實際上bookinfo元素的子元素都被移除了,但是新賦值的XML數據被轉義成文本內容,而不是一個新的子元素。
如果想用一個子樹代替另一個子樹,可以利用DOM擴展:
$book = simplexml_load_file('sxml.xml');
$bookinfo = dom_import_simplexml($book->bookinfo);
/* 移除bookinfo元素下的所有子元素*/
while ($bookinfo->firstChild) {
$bookinfo->removeChild($bookinfo->firstChild);
}
$bookinfo->appendChild(new DOMElement("title", "SimpleXML in PHP 5"));
print $book->bookinfo->asXML()."/n";
輸出結果:
<bookinfo>
<title>SimpleXML in PHP 5</title>
</bookinfo>
移除元素
可以用PHP內置函數unset()來將一個元素從樹中移除。unset()的參數必須是一個SimpleXMLElement,用屬性方法來訪問要移除的元素。例如,從chapter節點移除title元素:
$book = simplexml_load_file('sxml.xml');
$book->chapter->para[1] = "Removed CDATA";
unset($book->chapter->title);
print $book->chapter->asXML();
上述代碼執行後,chapter的結構爲:
<chapter id="navigation">
<para>Elements are accessed as properties</para>
<para>Removed CDATA</para>
</chapter>
將這個結果與下面代碼執行的結果想比較:
$book = simplexml_load_file('sxml.xml');
$book->chapter->para[1] = "Removed CDATA";
$title = $book->chapter->title;
unset($title);
print $book->chapter->asXML();
輸出結果
<chapter id="navigation">
<title>Acessing Elements</title>
<para>Elements are accessed as properties</para>
<para>Removed CDATA</para>
</chapter>
title元素沒有被移除,unset函數只對$title變量作用並沒有將title元素從樹中移除。
在移除一個元素時必須注意,用索引來指定的特定元素不會被移除:
$book = simplexml_load_file('sxml.xml');
$book->chapter->para[1] = "Removed CDATA";
unset($book->chapter->title[0]);
print $book->chapter->asXML();
輸出:
<chapter id="navigation">
<title>Acessing Elements</title>
<para>Elements are accessed as properties</para>
<para>Removed CDATA</para>
</chapter>
如果要移除所有的para元素時可以利用下面代碼:
$book = simplexml_load_file('sxml.xml');
unset($book->chapter->para);
print $book->chapter->asXML();
輸出:
<chapter id="navigation">
<title>Acessing Elements</title>
</chapter>
問題是如果你只想移除其中的一個para元素時要怎麼辦。這時可以再次用到DOM擴展:
$book = simplexml_load_file('sxml.xml');
$chapter = dom_import_simplexml($book->chapter);
$node = $chapter->lastChild;
while($node) {
if ($node->nodeName == "para") {
$chapter->removeChild($node);
$node = NULL;
break;
}
$node = $node->previousSibling;
}
print $book->chapter->asXML();
輸出:
<chapter id="navigation">
<title>Acessing Elements</title>
<para>Elements are accessed as properties</para>
</chapter>
所幸的是PHP5.2開始已經支持刪除用索引指定的元素了:
$book = simplexml_load_file('sxml.xml');
unset($book->chapter->para[1]);
print $book->chapter->asXML();
訪問屬性
讀取屬性
下面的代碼輸出了book元素中的lang屬性
$book = simplexml_load_file('sxml.xml');
print $book['lang'];
訪問用索引指定的元素的屬性:
$book = simplexml_load_file('sxml.xml');
print $book->chapter[0]['id'];
在不知道屬性名的情況下可以用attributes()方法來輸出屬性:
$book = simplexml_load_file('sxml.xml');
foreach($book->chapter->attributes() AS $attribute) {
print $attribute."/n";
}
如果要獲得位置的屬性名,可以使用DOM擴展:
$book = simplexml_load_file('sxml.xml');
foreach($book->chapter->attributes() AS $attribute) {
$att = dom_import_simplexml($attribute);
print $att->nodeName."/n";
print $attribute."/n";
}
修改屬性
修改屬性的值跟修改元素的值一樣,直接對其賦值就可以了:
$book = simplexml_load_file('sxml.xml');
$book['lang'] = "es";
print $book['lang'];
添加一個屬性也很簡單,如果對一個不存在的屬性名進行賦值就給元素創建一個新屬性
$book = simplexml_load_file('sxml.xml');
$book->bookinfo->author->firstname["prefix"] = "Mr.";
print $book->bookinfo->author->asXML();
輸出:
<author>
<firstname prefix="Mr.">Rob</firstname>
<surname>Richards</surname>
</author>
移除屬性
移除屬性也用到unset()函數:
$book = simplexml_load_file('sxml.xml');
$book->bookinfo->author->firstname["prefix"] = "Mr.";
print $book->bookinfo->author->firstname->asXML()."/n/n";
unset($book->bookinfo->author->firstname["prefix"]);
print $book->bookinfo->author->firstname->asXML();
輸出:
<firstname prefix="Mr.">Rob</firstname>
<firstname>Rob</firstname>
擴展SimpleXMLElement類
class mySXE extends SimpleXMLElement {
function appendChild($name, $content) {
$dom = dom_import_simplexml($this);
$dom->appendChild($dom->ownerDocument->createElement($name, $content));
}
}
當實例化擴展的類時,文檔的每個節點對象的類型都是擴展類的類型。
$sxe = new mySXE("<root><node1></node1></root>");
$sxe->node1->appendChild("node2", "content");
print $sxe->asXML();
輸出:
<?xml version="1.0"?>
<root><node1><node2>content</node2></node1></root>
使用new方法可以用來處理字符串類型的XML,如果XML保存在一個文件中,那麼可以將擴展的類名作爲第二個參數傳給simplexml_load_string或simplexml_load_file
$sxe = simplexml_load_string("<root><node1></node1></root>", "mySXE");
$sxe->node1->appendChild("node2", "content");
print $sxe->asXML();
輸出結果與用new關鍵字輸出的結果一樣。
在SimpleXML中使用命名空間
將清單7-1的內容改爲
<?xml version="1.0" encoding="UTF-8"?>
<book lang="en">
<bookinfo xmlns="http://www.example.com/ns1">
<title>SimpleXML in PHP 5</title>
<author>
<firstname>Rob</firstname>
<surname>Richards</surname>
</author>
<copyright>
<year>2005</year>
<holder>Rob Richards</holder>
</copyright>
</bookinfo>
</book>
如果試圖用普通的方法來訪問元素或屬性,你會分析這並不可行,例如:
$book = simplexml_load_file('sxmlns.xml');
print $book["lang"]."/n";
print $book->bookinfo->title."/n";
輸出的結果是兩行空白。
在 訪問命名空間節點前,必須使用children()和attributes()方法。這兩個方法不僅可以在沒有指定參數的時候使用,也可以在指定一個 URI命名空間作爲參數使用。如果一個SimleXMLElement對象是從這兩個方法返回的,那麼你就可以像普通的元素和屬性一樣訪問命名空間下的元 素和屬性:
$book = simplexml_load_file('sxmlns.xml');
/* 返回 http://www.example.com/ns2 命名空間下的所有屬性 */
$bookatts = $book->attributes("http://www.example.com/ns2");
print $bookatts["lang"]."/n";
/* 返回 http://www.example.com/ns1 命名空間下的所有元素*/
$bookns = $book->children("http://www.example.com/ns1");
$bookinfo = $bookns->bookinfo;
/* 重置命名空間來訪問非命名空間的元素 */
$nonsbkinfo = $bookinfo->children();
print $nonsbkinfo->title."/n";
children ()和attributes()方法可以被看做是過濾器,如果沒有參數或者傳遞一個NULL作爲參數,這兩個方法將返回非命名空間下的元素或屬性;否則將 返回特定命名空間下的元素或屬性。在重置之前,命名空間仍然起作用並且被子節點繼承。例如,使用$bookinfo被設置爲命名空間http://www.example.com/ns1的對象,可以使用 print $bookinfo->author->firstname來但因author中的firstname元素。所有的元素都在命名空間下,因此你在創建$bookinfo對象時不必一直使用children()設置命名空間。
本文轉載於http://blog.csdn.net/guoguo1980/article/details/2436318