我想在XML文件中的特定位置插入带子项的节点。我该怎么做?
例如。如果我有一个XML:
<myvalues>
<image name="img01">
<src>test</src>
</image>
<image name="img02">
<src>test</src>
</image>
<image name="img03">
<src>test</src>
</image>
</myvalues>
我想插入:
<image name="img11">
<src>test2</src>
</image>
介于<image name="img01">
之间<image name="img02">
。我该怎么做呢?我现在正在使用SimpleXML来读取XML。
感谢。
编辑:我尝试了以下代码。但是,新节点添加在XML结构外部的XML底部。
$xml = new DomDocument();
$xml->preserveWhitespace = false;
$xml->load('myXMLFile.xml');
$newNode = $xml->createElement('tryimage');
$xpath = new DOMXpath($xml);
$elements = $xpath->query('/myvalues/image[name="img01"]');
$refNode = $elements->item(0);
$xml->insertBefore($newNode, $refNode->nextSibling);
header('Content-Type: text/plain');
echo $xml->saveXML();
输出是这样的:
<xml....>
<myvalues>
<image name="01">
</image>
.
.
.
</myvalues>
<tryimage />
答案 0 :(得分:3)
嗯,我用SimpleXML看不出简单的方法(毕竟它应该很简单)。
一种方法是将myvalues节点移到DOMDocument,在那里添加节点,然后用dom节点替换它。鉴于$myvalues
是SimpleXML中的<myvalues>
节点:
$domMyValues = dom_import_simplexml($myvalues);
$newNode = $domMyValues->ownerDocument->createElement('mynewelement');
//Apply attributes and whatever to $newNode
//find the node that you want to insert it before (from the $domMyValues class
$nodes = $domMyValues->getElementsByTagName('image');
$refNode = null;
foreach ($nodes as $node) {
if ($node->getAttribute('name') == 'img02') {
$refNode = $node;
}
}
$domMyValues->insertBefore($newNode, $refNode);
注意,没有必要转换回SimpleXML,因为对DOMElement的任何更改都将自动应用于SimpleXML版本...如果找不到$refNode
,它将自动附加新的子项(因为它不存在,等等)......
编辑:添加XPath
用这个替换foreach块(如果我的查询正确,则在功能上等效):
$xpath = new DOMXpath($domMyValues->ownerDocument);
$elements = $xpath->query('//image[@name="img02"]');
$refNode = $elements->item(0);
由于DOMNodeList::item()
对于不存在的偏移量返回null,我们甚至不需要检查其中是否有项目。
现在,您可能需要/想要将xpath查询调整为更多/更少特定。这是decent tutorial ...
修改2
我忘了xpath需要一个@
字符来告诉它检查一个属性。
这是我的工作代码(因为我不知道你的确切架构):
$x = '<?xml version="1.0" ?>
<myvalues>
<images>
<image name="01">Foo</image>
<image name="02">Bar</image>
</images>
</myvalues>';
$dom = new DomDocument();
$dom->loadXML($x);
$xpath = new DOMXpath($dom);
$elements = $xpath->query('//images/image[@name="01"]');
$elements = $xpath->query('//image[@name="01"]');
$elements = $xpath->query('/myvalues/images/image[@name="01"]');
答案 1 :(得分:2)
如ircmaxel's answer中所述,您可以使用DOM类/方法来执行您想要的操作。下面是一个简洁的(可能比真正想要使用的代码更少的代码)在另一个之后插入SimpleXMLElement的示例。
function insertAfter(SimpleXMLElement $new, SimpleXMLElement $target) {
$target = dom_import_simplexml($target);
$new = $target->ownerDocument->importNode(dom_import_simplexml($new), true);
if ($target->nextSibling) {
$target->parentNode->insertBefore($new, $target->nextSibling);
} else {
$target->parentNode->appendChild($new);
}
}
$sxe = new SimpleXMLElement($xml);
$img = $sxe->xpath('//image[@name="img01"]'); // xpath returns an array
if (!empty($img)) {
$new = new SimpleXMLElement('<image name="img11" foo="bar"><src>test</src></image>');
insertAfter($new, $img[0]);
}
foreach ($sxe as $image) {
echo $image['name'] . PHP_EOL;
}
/*
img01
img11
img02
img03
*/