PHP通過SimpleXML訪問xml文檔 (二)

修改內容

利用SimpleXML修改元素內容非常方便,你可以改變或移除樹中的某個元素,但是不能直接在樹中添加一個元素。要添加一個元素,可以使用DOM的互操作性:

  1. $xml = "<root><node1>content</node1></root>";

  2. $sxe = new SimpleXMLElement($xml);

  3. $dom = dom_import_simplexml($sxe);

  4. $dom->appendChild(new DOMElement("node2", "content2"));

  5. print $sxe->asXML();

輸出:

  1. <?xml version="1.0"?>

  2. <root><node1>content</node1><node2>content2</node2></root>

編輯文本內容

可以利用SimpleXML的屬性賦值方法來直接編輯一個元素的內容,要主意的是如果文檔中有多個元素名一樣的元素,如果沒有使用索引來指定要編輯哪個元素時PHP將發出一個警告。如:

  1. $book = simplexml_load_file('sxml.xml');

  2. /* Modify an unspecified para element where multiple para elements exist */

  3. $book->chapter->para = "Removed CDATA";

輸出:
Warning: main() [/phpmanual/function.main.html]: Cannot assign to an array of nodes
(duplicate subnodes or attr detected)

必須給para指定索引告訴程序你要編輯哪個元素:

  1. $book = simplexml_load_file('sxml.xml');

  2. $book->chapter->para[1] = "Removed CDATA";

  3. print $book->chapter->asXML();

輸出:

  1. <chapter id="navigation">

  2.     <title>Acessing Elements</title>

  3.     <para>Elements are accessed as properties</para>

  4.     <para>Removed CDATA</para>

  5. </chapter>

這樣,第二個para元素的內容被改爲Removed CDATA。如果要編輯一個在文檔中唯一存在的元素可不必指定索引,直接修改。如修改title:

  1. $book = simplexml_load_file('sxml.xml');

  2. $book->chapter->title = "New Title";

  3. $book->chapter->para[1] = "Removed CDATA";

  4. print $book->chapter->asXML();

輸出:

  1. <chapter id="navigation">

  2.     <title>New Title</title>

  3.     <para>Elements are accessed as properties</para>

  4.     <para>Removed CDATA</para>

  5. </chapter>

強烈建議使用索引來編輯元素,除非你對文檔的結果非常確定。使用索引來編輯title元素會比較安全,如$book->chapter->title[0] = “New Title”;這行代碼用索引[0]指定要編輯第一個title。

編輯有子樹的元素

  1. $book = simplexml_load_file('sxml.xml');

  2. $cholder = $book->bookinfo->copyright->holder;

  3. print $cholder->asXML()."/n";

  4. $book->bookinfo = "No Book Info";

  5. print $book->bookinfo->asXML()."/n";

  6. print $cholder->asXML()."/n";

輸出:

  1. <holder>Rob Richards</holder>

  2. <bookinfo>No Book Info</bookinfo>

  3. Warning: SimpleXMLElement::asXML() [/phpmanual/function.asXML.html]: Node no

  4. 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元素中的子元素用字符串 代替。

  1. $book = simplexml_load_file('sxml.xml');

  2. $book->bookinfo = "<title>SimpleXML in PHP 5</title>";

  3. print $book->bookinfo->asXML()."/n";

如果你認爲上述代碼將bookinfo中的內容清空後再給bookinfo創建了一個子節點title,那麼你錯了。輸出結果是
<title>SimpleXML in PHP 5</title>
實際上bookinfo元素的子元素都被移除了,但是新賦值的XML數據被轉義成文本內容,而不是一個新的子元素。

如果想用一個子樹代替另一個子樹,可以利用DOM擴展:

  1. $book = simplexml_load_file('sxml.xml');

  2. $bookinfo = dom_import_simplexml($book->bookinfo);

  3. /* 移除bookinfo元素下的所有子元素*/

  4. while ($bookinfo->firstChild) {

  5. $bookinfo->removeChild($bookinfo->firstChild);

  6. }

  7. $bookinfo->appendChild(new DOMElement("title", "SimpleXML in PHP 5"));

  8. print $book->bookinfo->asXML()."/n";

輸出結果:

  1. <bookinfo>

  2. <title>SimpleXML in PHP 5</title>

  3. </bookinfo>

移除元素

可以用PHP內置函數unset()來將一個元素從樹中移除。unset()的參數必須是一個SimpleXMLElement,用屬性方法來訪問要移除的元素。例如,從chapter節點移除title元素:

  1. $book = simplexml_load_file('sxml.xml');

  2. $book->chapter->para[1] = "Removed CDATA";

  3. unset($book->chapter->title);

  4. print $book->chapter->asXML();

上述代碼執行後,chapter的結構爲:

  1. <chapter id="navigation">

  2.  

  3.     <para>Elements are accessed as properties</para>

  4.     <para>Removed CDATA</para>

  5. </chapter>

將這個結果與下面代碼執行的結果想比較:

  1. $book = simplexml_load_file('sxml.xml');

  2. $book->chapter->para[1] = "Removed CDATA";

  3. $title = $book->chapter->title;

  4. unset($title);

  5. print $book->chapter->asXML();

輸出結果

  1. <chapter id="navigation">

  2.     <title>Acessing Elements</title>

  3.     <para>Elements are accessed as properties</para>

  4.     <para>Removed CDATA</para>

  5. </chapter>

title元素沒有被移除,unset函數只對$title變量作用並沒有將title元素從樹中移除。

在移除一個元素時必須注意,用索引來指定的特定元素不會被移除:

  1. $book = simplexml_load_file('sxml.xml');

  2. $book->chapter->para[1] = "Removed CDATA";

  3. unset($book->chapter->title[0]);

  4. print $book->chapter->asXML();

輸出:

  1. <chapter id="navigation">

  2.     <title>Acessing Elements</title>

  3.     <para>Elements are accessed as properties</para>

  4.     <para>Removed CDATA</para>

  5. </chapter>

如果要移除所有的para元素時可以利用下面代碼:

  1. $book = simplexml_load_file('sxml.xml');

  2. unset($book->chapter->para);

  3. print $book->chapter->asXML();

輸出:

  1. <chapter id="navigation">

  2.     <title>Acessing Elements</title>

  3.  

  4.  

  5. </chapter>

問題是如果你只想移除其中的一個para元素時要怎麼辦。這時可以再次用到DOM擴展:

  1. $book = simplexml_load_file('sxml.xml');

  2. $chapter = dom_import_simplexml($book->chapter);

  3. $node = $chapter->lastChild;

  4. while($node) {

  5.     if ($node->nodeName == "para") {

  6.         $chapter->removeChild($node);

  7.         $node = NULL;

  8.         break;

  9.     }

  10.     $node = $node->previousSibling;

  11. }

  12. print $book->chapter->asXML();

輸出:

  1. <chapter id="navigation">

  2.     <title>Acessing Elements</title>

  3.     <para>Elements are accessed as properties</para>

  4.  

  5. </chapter>

所幸的是PHP5.2開始已經支持刪除用索引指定的元素了:

  1. $book = simplexml_load_file('sxml.xml');

  2. unset($book->chapter->para[1]);

  3. print $book->chapter->asXML();

訪問屬性

讀取屬性

下面的代碼輸出了book元素中的lang屬性

  1. $book = simplexml_load_file('sxml.xml');

  2. print $book['lang'];

訪問用索引指定的元素的屬性:

  1. $book = simplexml_load_file('sxml.xml');

  2. print $book->chapter[0]['id'];

在不知道屬性名的情況下可以用attributes()方法來輸出屬性:

  1. $book = simplexml_load_file('sxml.xml');

  2. foreach($book->chapter->attributes() AS $attribute) {

  3.     print $attribute."/n";

  4. }

如果要獲得位置的屬性名,可以使用DOM擴展:

  1. $book = simplexml_load_file('sxml.xml');

  2. foreach($book->chapter->attributes() AS $attribute) {

  3.     $att = dom_import_simplexml($attribute);

  4.     print $att->nodeName."/n";

  5.     print $attribute."/n";

  6. }

修改屬性
修改屬性的值跟修改元素的值一樣,直接對其賦值就可以了:

  1. $book = simplexml_load_file('sxml.xml');

  2. $book['lang'] = "es";

  3. print $book['lang'];

添加一個屬性也很簡單,如果對一個不存在的屬性名進行賦值就給元素創建一個新屬性

  1. $book = simplexml_load_file('sxml.xml');

  2. $book->bookinfo->author->firstname["prefix"] = "Mr.";

  3. print $book->bookinfo->author->asXML();

輸出:

  1. <author>

  2.     <firstname prefix="Mr.">Rob</firstname>

  3.     <surname>Richards</surname>

  4. </author>

移除屬性

移除屬性也用到unset()函數:

  1. $book = simplexml_load_file('sxml.xml');

  2. $book->bookinfo->author->firstname["prefix"] = "Mr.";

  3. print $book->bookinfo->author->firstname->asXML()."/n/n";

  4. unset($book->bookinfo->author->firstname["prefix"]);

  5. print $book->bookinfo->author->firstname->asXML();

輸出:

  1. <firstname prefix="Mr.">Rob</firstname>

  2.  

  3. <firstname>Rob</firstname>

擴展SimpleXMLElement類

  1. class mySXE extends SimpleXMLElement {

  2.     function appendChild($name, $content) {

  3.         $dom = dom_import_simplexml($this);

  4.         $dom->appendChild($dom->ownerDocument->createElement($name, $content));

  5.     }

  6. }

當實例化擴展的類時,文檔的每個節點對象的類型都是擴展類的類型。

  1. $sxe = new mySXE("<root><node1></node1></root>");

  2. $sxe->node1->appendChild("node2", "content");

  3. print $sxe->asXML();

輸出:

  1. <?xml version="1.0"?>

  2. <root><node1><node2>content</node2></node1></root>

使用new方法可以用來處理字符串類型的XML,如果XML保存在一個文件中,那麼可以將擴展的類名作爲第二個參數傳給simplexml_load_string或simplexml_load_file

  1. $sxe = simplexml_load_string("<root><node1></node1></root>", "mySXE");

  2. $sxe->node1->appendChild("node2", "content");

  3. print $sxe->asXML();

輸出結果與用new關鍵字輸出的結果一樣。

在SimpleXML中使用命名空間

將清單7-1的內容改爲

  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <book lang="en">

  3. <bookinfo xmlns="http://www.example.com/ns1">

  4.     <title>SimpleXML in PHP 5</title>

  5.     <author>

  6.         <firstname>Rob</firstname>

  7.         <surname>Richards</surname>

  8.     </author>

  9.     <copyright>

  10.         <year>2005</year>

  11.         <holder>Rob Richards</holder>

  12.     </copyright>

  13.     </bookinfo>

  14. </book>

如果試圖用普通的方法來訪問元素或屬性,你會分析這並不可行,例如:

  1. $book = simplexml_load_file('sxmlns.xml');

  2. print $book["lang"]."/n";

  3. print $book->bookinfo->title."/n";

輸出的結果是兩行空白。

在 訪問命名空間節點前,必須使用children()和attributes()方法。這兩個方法不僅可以在沒有指定參數的時候使用,也可以在指定一個 URI命名空間作爲參數使用。如果一個SimleXMLElement對象是從這兩個方法返回的,那麼你就可以像普通的元素和屬性一樣訪問命名空間下的元 素和屬性:

  1. $book = simplexml_load_file('sxmlns.xml');

  2. /* 返回 http://www.example.com/ns2 命名空間下的所有屬性 */

  3. $bookatts = $book->attributes("http://www.example.com/ns2");

  4. print $bookatts["lang"]."/n";

  5. /* 返回 http://www.example.com/ns1 命名空間下的所有元素*/

  6. $bookns = $book->children("http://www.example.com/ns1");

  7. $bookinfo = $bookns->bookinfo;

  8. /* 重置命名空間來訪問非命名空間的元素 */

  9. $nonsbkinfo = $bookinfo->children();

  10. 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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章