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

Posted

技术标签:

【中文标题】如何在不使用其父级的情况下设置 SimpleXmlElement 的文本值?【英文标题】:How can I set text value of SimpleXmlElement without using its parent? 【发布时间】:2011-03-10 08:52:21 【问题描述】:

我想设置 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>

【问题讨论】:

【参考方案1】:

您可以使用 SimpleXMLElement 自引用

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

查看后发现

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

这也适用于unset 中所述的an answer to 操作:

Remove a child with a specific attribute, in SimpleXML for PHP

【讨论】:

请注意,使用对象表示法的第一个变体在 PHP 7 中似乎不再适用。【参考方案2】:

真正的答案是:你有点做不到。

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

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

【讨论】:

为什么这是真正的答案? 那是因为在撰写本文时没有支持的方法,而且我认为它没有改变。设置名为“0”的不存在节点的值会更改节点的 textContent 的事实可能是一个副作用,这完全是运气的结果。它可能会意外停止工作。 接受的答案中概述了支持的方法,在您在这里回答很长一段时间时已经存在(只是要求了解更多)。这种方式实际上是受支持的,它记录在 PHP 的 src 中,您可以在此处找到实现:lxr.php.net/xref/PHP_5_3/ext/simplexml/… - 零偏移量始终可用于所有元素节点。此外,您的答案也错过了check the node-type of a SimpleXMLElement object,并有可能产生错误和副作用。 这仍然是一个实现细节。您必须链接到(未注释的)源代码而不是手册这一事实只会使其更清晰。通过记录它让开发人员正式支持它,我将其视为官方功能。否则,对我来说,这实际上是一种无证行为。 这应该是正确的答案,因为它是很久以前php规定的技术。公认的答案是黑客攻击和使用风险自负的“解决方案”。

以上是关于如何在不使用其父级的情况下设置 SimpleXmlElement 的文本值?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不设置面板标题的情况下使 p:dashboard 组件可拖动

如何在不添加我自己的 prop 的情况下将内置的 Vuetify 组件 prop 从其父级应用到 SFC 的根元素?

在不改变状态、道具或父级的情况下反应子级渲染

Firebase:在不知道父级的情况下查询内部子级

如何将 xml 图像调整为其父级的高度

如何使用 Swift 从其父级的笔尖创建视图