2010-06-30 21 views
18

我想設置()與XPath發現了一些節點的文本如何設置SimpleXmlElement的文本值而不使用其父項?

<?php 

$args = new SimpleXmlElement(
<<<XML 
<a> 
    <b> 
    <c>text</c> 
    <c>stuff</c> 
    </b> 
    <d> 
    <c>code</c> 
    </d> 
</a> 
XML 
); 

// I want to set text of some node found by xpath 
// Let's take (//c) for example 

// convoluted and I can't be sure I'm setting right node 
$firstC = reset($args->xpath("//c[1]/parent::*")); 
$firstC->c[0] = "test 1"; 

// like here: Found node is not actually third in its parent. 
$firstC = reset($args->xpath("(//c)[3]/parent::*")); 
$firstC->c[2] = "test 2"; 

// following won't work for obvious reasons, 
// some setText() method would be perfect but I can't find nothing similar, 
$firstC = reset($args->xpath("//c[1]")); 
$firstC = "test"; 

// maybe there's some hack for it? 
$firstC = reset($args->xpath("//c[1]")); 
$firstC->{"."} = "test"; // nope, just adds child named . 
$firstC->{""} = "test"; // still not right, 'Cannot write or create unnamed element' 
$firstC["."] = "test"; // still no luck, adds attribute named . 
$firstC[""] = "test"; // still no luck, 'Cannot write or create unnamed attribute' 
$firstC->addChild('','test'); // grr, 'SimpleXMLElement::addChild(): Element name is required' 
$firstC->addChild('.','test'); // just adds another child with name . 

echo $args->asXML(); 

// it outputs: 
// 
// PHP Warning: main(): Cannot add element c number 2 when only 1 such elements exist 
// PHP Warning: main(): Cannot write or create unnamed element 
// PHP Warning: main(): Cannot write or create unnamed attribute 
// PHP Warning: SimpleXMLElement::addChild(): Element name is required 
// <?xml version="1.0"? > 
// <a> 
// <b> 
// <c .="test">test 1<.>test</.><.>test</.></c> 
// <c>stuff</c> 
// </b> 
// <d> 
// <c>code</c> 
// <c>test 2</c></d> 
// </a> 

回答

34

您可以用的SimpleXMLElement自我參照做:

$firstC->{0} = "Victory!!"; // hackity, hack, hack! 
// -or- 
$firstC[0] = "Victory!!"; 

看着

var_dump((array) reset($xml->xpath("(//c)[3]"))) 
後發現

這也適用unset操作,如an answer to中所述:

+4

你救了我下午。 – Minkiele 2013-05-13 14:11:20

+0

請注意,使用對象表示法的第一個變體在PHP 7中似乎不再有效。 – 2017-09-14 10:17:45

6

真正的答案是:你有種不能。

另一方面,您可以使用DOM,例如,

dom_import_simplexml($node)->nodeValue = 'foo'; 
+0

爲什麼這是真正的答案? – hakre 2013-09-30 09:04:00

+1

這是因爲在撰寫本文時沒有支持的方式來做到這一點,我認爲它沒有改變。設置名爲「0」的不存在節點的值改變節點的textContent的事實可能是一個副作用,這是純粹運氣的結果。它可能會意外停止工作。 – 2013-09-30 10:42:03

+2

支持的方式在接受的答案中已經概述,在那裏你已經有了相當一段時間的回答(只是要求學習更多)。這種方式實際上是受支持的,它在PHP的src中有記錄,您可以在這裏找到實現:http://lxr.php.net/xref/PHP_5_3/ext/simplexml/simplexml.c#sxe_get_element_by_offset - 零偏移量始終可用於所有元素節點。此外,您的答案會錯過[檢查SimpleXMLElement對象的節點類型](http://stackoverflow.com/a/14829309/367456)以及產生錯誤和副作用的風險。 – hakre 2013-09-30 11:09:02

相關問題