2011-02-27 42 views
5

由於PHP代碼獲取一個節點的文本部分:使用PHP簡單的XML

$xml = <<<EOF 
<articles> 
<article> 
This is a link 
<link>Title</link> 
with some text following it. 
</article> 
</articles> 
EOF; 

function traverse($xml) { 
    $result = ""; 
    foreach($xml->children() as $x) { 
     if ($x->count()) { 
      $result .= traverse($x); 
     } 
     else { 
      $result .= $x; 
     } 
    } 
    return $result; 
} 

$parser = new SimpleXMLElement($xml); 
traverse($parser); 

我預期的功能遍歷()返回:

This is a link Title with some text following it. 

然而,它只返回:

Title 

有沒有辦法使用simpleXML來獲得預期的結果(顯然是爲了消費數據而不是僅僅使用r就像在這個簡單的例子中一樣)?

感謝, N.

回答

15

可能有辦法達到你想要只使用了SimpleXML什麼,但在這種情況下,最簡單的方法是使用DOM。好消息是,如果你已經使用了SimpleXML,你沒有任何改變的DOM和SimpleXML是basically interchangeable

// either 
$articles = simplexml_load_string($xml); 
echo dom_import_simplexml($articles)->textContent; 

// or 
$dom = new DOMDocument; 
$dom->loadXML($xml); 
echo $dom->documentElement->textContent; 

假設你的任務是遍歷每個<article/>並獲得它的內容,你的代碼看起來像

$articles = simplexml_load_string($xml); 
foreach ($articles->article as $article) 
{ 
    $articleText = dom_import_simplexml($article)->textContent; 
} 
+0

這實際上產生了我期待的確切結果 - 實際上並沒有解決遍歷Xml文檔的底層問題。 – Nikolaj 2011-02-27 16:28:35

+1

您將無法使用SimpleXML「遍歷」或迭代文本節點。或者至少,如果可能的話,它將被設計/不切實際。使用SimpleXML讓東西變得更容易,然後將所選節點導入DOM,以訪問不屬於SimpleXML的功能。 – 2011-02-27 17:08:28

+0

是的,確實如此。看來我必須學習那種困難的方式。 – Nikolaj 2011-02-27 17:17:11

1

您可以只用對待它就像一根繩索讓用SimpleXML DOM元素的文本節點:

foreach($xml->children() as $x) { 
    $result .= "$x" 

然而,這種打印出:

This is a link 

with some text following it. 
TitleTitle 

..因爲文本節點被視爲一個塊,並且無法確定子文件在文本節點內的位置。由於其他人{},子節點也被添加了兩次,但是您可以將其取出。

對不起,如果我沒有什麼幫助,但我不認爲有什麼方法可以找出子節點在文本節點中的位置,除非xml是一致的(但爲什麼不使用標籤)。如果你知道你想剝離文本的元素,strip_tags()將工作得很好。

+0

它總是幫助知道你要完成什麼是不可能的。不幸的是,我不擁有XML,所以它就是這樣。你知道在php中的其他解析器是否更適合我的任務嗎? – Nikolaj 2011-02-27 09:24:18

+0

我不知道任何現有的..也許你可以寫一個! – 2011-02-27 14:39:17

+0

在討論了錯誤的(解析器?)樹之後,似乎DOM是我們需要處理這類XML的朋友。 – Nikolaj 2011-02-27 16:18:13

0

像@tandu說,這是不可能的,但如果你可以改變你的XML,這將工作:

$xml = <<<EOF 
<articles> 
    <article> 
     This is a link 
    </article> 
    <link>Title</link> 
    <article> 
     with some text following it. 
    </article> 
</articles> 
3

所以,我的問題的簡單答案是:Simplexml無法處理這種類型的XML。改用DomDocument。

此示例說明如何遍歷整個XML。 DomDocument似乎可以用於任何XML,而SimpleXML則要求XML很簡單。

function attrs($list) { 
    $result = ""; 
    foreach ($list as $attr) { 
     $result .= " $attr->name='$attr->value'"; 
    } 
    return $result; 
} 

function parseTree($xml) { 
    $result = ""; 
    foreach ($xml->childNodes AS $item) { 
     if ($item->nodeType == 1) { 
      $result .= "<$item->nodeName" . attrs($item->attributes) . ">" . parseTree($item) . "</$item->nodeName>"; 
     } 
     else { 
      $result .= $item->nodeValue; 
     } 
    } 
    return $result; 
} 

$xmlDoc = new DOMDocument(); 
$xmlDoc->loadXML($xml); 

print parseTree($xmlDoc->documentElement); 

你也可以使用SimpleXML加載XML,然後使用dom_import_simplexml()作爲喬希說,將其轉換爲DOM。如果您使用simpleXml過濾節點進行解析,這將非常有用,例如使用XPath。

但是,我實際上並沒有使用simpleXML,所以對我來說這將會花費很長時間。

$simpleXml = new SimpleXMLElement($xml); 
$xmlDom = dom_import_simplexml($simpleXml); 

print parseTree($xmlDom); 

謝謝大家的幫助!

4
node->asXML();// It's the simple solution i think !! 
+0

你有沒有用OP的數據試過這個?它實際上工作嗎? – 2011-08-23 09:51:25

1

這已經被回答了,但CASTING TO STRING(即$ sString =(string)oSimpleXMLNode-> TagName)總是爲我工作。

+0

echo(string)$ xmlNode; – 2014-08-22 07:13:18

0

試試這個:

$parser = new SimpleXMLElement($xml); 
echo strip_tags($parser->asXML()); 

這幾乎等同於:

$parser = simplexml_load_string($xml); 
echo dom_import_simplexml($parser)->textContent;