这是我的xml:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<node/>
<node>
<child id="child1">
<subchild1/>
<subchild2/>
</child>
<child id="child2">
<subchild1/>
<subchild2/>
</child>
<child id="child3">
<subchild1/>
<subchild2/>
</child>
</node>
</root>
当我使用 insertbefore 插入节点时,它可以工作,但该节点的代码没有缩进:
$next = $xpath->query('/root/node/child[@id="child1"]/subchild2');
// Create the new element
$element = $dom->createElement('subchildmiddle');
$parent = $xpath->query('/root/node/child[@id="child1"]');
$parent->item(0)->insertBefore($element, $next->item(0));
结果是这样的:
<child id="child1">
<subchild1/>
<subchildmiddle><subchild2/>
</child>
但我会:
<child id="child1">
<subchild1/>
<subchildmiddle>
<subchild2/>
</child>
这可能吗?我用了
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
(我在之前的问题中找到了它)来格式化代码并且它有效,但不适用于子孩子中间!
加载 XML 文档之前必须禁用preserveWhiteSpace
。该选项配置分析器,使其忽略空格文本节点。
格式化并不总是完美地工作,它会在节点之间添加空格节点。但是空格节点可以有意义(例如<strong class="firstLetter">H</strong>ello
)。序列化程序将尝试避免添加更改内容的空格节点,从而抛弃格式。
此外,还可以优化您的源:
$document = new DOMDocument();
$document->preserveWhiteSpace = FALSE;
$document->formatOutput = TRUE;
$document->loadXml($xml);
$xpath = new DOMXpath($document);
foreach ($xpath->evaluate('/root/node/child[@id="child1"][1]') as $parent) {
$parent->insertBefore(
$document->createElement('subchildmiddle'),
$xpath->evaluate('subchild2', $parent)->item(0)
);
}
echo $document->saveXml();
输出:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<node/>
<node>
<child id="child1">
<subchild1/>
<subchildmiddle/>
<subchild2/>
</child>
<child id="child2">
<subchild1/>
<subchild2/>
</child>
<child id="child3">
<subchild1/>
<subchild2/>
</child>
</node>
</root>
这样,第一个表达式将获取父节点。第二个表达式使用父节点作为上下文,如果它返回空节点列表,则该节点将添加为最后一个子节点。这样可以避免在->item(0)
上调用方法,如果表达式返回空列表,则会触发错误。