2010-06-30 31 views
18

Tôi muốn thiết lập văn bản của một số nút được tìm thấy bởi xpath()Làm cách nào để đặt giá trị văn bản của SimpleXmlElement mà không sử dụng giá trị gốc?

<?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> 

Trả lời

34

Bạn có thể làm với một SimpleXMLElement tự tham khảo:

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

tìm thấy sau khi nhìn vào

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

Điều này cũng hoạt động với các hoạt động unset như được nêu trong an answer to:

+4

Bạn đã lưu buổi chiều của mình. – Minkiele

+0

Lưu ý rằng biến thể đầu tiên sử dụng ký pháp đối tượng dường như không hoạt động nữa trong PHP 7. –

6

Câu trả lời thật là: bạn loại không thể.

Mặt khác, bạn có thể sử dụng DOM cho nó, ví dụ:

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

Tại sao loại câu trả lời thực sự lại như vậy? – hakre

+1

Đó là bởi vì tại thời điểm viết không có cách nào được hỗ trợ để làm điều đó, và tôi không nghĩ rằng nó đã thay đổi. Thực tế là thiết lập giá trị của một nút không tồn tại có tên là "0" thay đổi textContent của một nút có thể là một tác dụng phụ, kết quả của sự may mắn tuyệt đối. Nó có thể bất ngờ ngừng hoạt động. –

+2

Cách được hỗ trợ để thực hiện điều đó được nêu trong câu trả lời được chấp nhận đã có tại thời điểm bạn trả lời ở đây một thời gian khá lâu (chỉ cần hỏi để tìm hiểu thêm). Bằng cách đó thực sự được hỗ trợ và nó được ghi lại trong src của PHP, bạn tìm thấy việc thực hiện ở đây: http://lxr.php.net/xref/PHP_5_3/ext/simplexml/simplexml.c#sxe_get_element_by_offset - bù đắp zero luôn luôn có sẵn cho tất cả nút phần tử. Ngoài ra câu trả lời của bạn còn bỏ sót để [kiểm tra kiểu nút của một đối tượng SimpleXMLElement] (http://stackoverflow.com/a/14829309/367456) và các rủi ro để tạo ra các lỗi và cũng có các tác dụng phụ. – hakre

Các vấn đề liên quan