如何在不使用其父项的情况下设置SimpleXmlElement的文本值?

Kam*_*zot 21 php xml xpath simplexml

我想设置xpath()找到的某个节点的文本

<?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>
Run Code Online (Sandbox Code Playgroud)

Kam*_*zot 37

您可以使用SimpleXMLElement自引用:

$firstC->{0} = "Victory!!"; // hackity, hack, hack!
//  -or-
$firstC[0]   = "Victory!!";
Run Code Online (Sandbox Code Playgroud)

看了之后找到了

var_dump((array) reset($xml->xpath("(//c)[3]")))
Run Code Online (Sandbox Code Playgroud)

这也适用unset以下答案中概述的操作:

  • 你救了我的下午. (4认同)
  • 请注意,使用对象表示法的第一个变体在 PHP 7 中似乎不再适用。 (2认同)

Jos*_*vis 8

真正的答案是:你有点不能.

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

dom_import_simplexml($node)->nodeValue = 'foo';
Run Code Online (Sandbox Code Playgroud)

  • 支持的方式在接受的答案中概述,当时你已经在这里回答了很长一段时间(只是被要求了解更多信息).这种方式实际上是受支持的,它在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),并且存在产生错误和副作用的风险. (2认同)