php - 使用insertbefore时的xml缩进

时间:2016-02-04 09:51:51

标签: php xml dom xpath xml-parsing

这是我的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;

(我在前面的问题中找到了)格式化代码并且它可以工作,但不适用于子孙分区!

1 个答案:

答案 0 :(得分:1)

在加载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();

Output

<?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)上调用方法,如果表达式返回空列表,则会触发错误。