【问题标题】:How to solve the issue of multi-level XML using Dom Document in PHP?如何在 PHP 中使用 Dom Document 解决多级 XML 的问题?
【发布时间】:2018-02-20 15:37:57
【问题描述】:

我有一个类似 ip=["A-B-C-D","A-B-E-D","A-B-F-D"] 的数组。现在我必须基于这个层次结构创建一个 XML。 XML 的预期输出将是。

<start>
<comm>
  <name>A</name>
    <comm>
      <name>B</name>
        <comm>
          <name>C</name>
            <comm>
              <name>D</name>
            </comm>
        </comm>
        <comm>
          <name>E</name>
            <comm>
              <name>D</name>
            </comm>
        </comm>
        <comm>
          <name>F</name>
            <comm>
              <name>D</name>
            </comm>
        </comm>
    </comm>
</comm>

基本上,C、E 和 F 将是兄弟姐妹,它们将位于 &lt;comm&gt;&lt;name&gt;C/E/F&lt;/name&gt;&lt;/comm&gt; 部分内,然后在该标签内将是 D。每个元素都需要位于 comm 和名称标签内。

我已经完成了如下代码,

$basecomm = $doc->createElement( "start" );
$doc->appendChild( $basecomm );
$base = $doc->getElementsByTagName("comm");

foreach($ip as $input){
    $arr=explode("-",$input);


    foreach ($arr as $a){
        $newcomm=null;
        foreach ( $base as $community )   {

            foreach($community->childNodes as $nextElement){
            if ( $nextElement instanceof DOMElement
                    && $nextElement->tagName == 'name' && $nextElement->nodeValue==$a)   {
                        $newcomm = $nextElement->parentNode;
                    }
        }
        }
        if($newcomm==null){
        $newcomm=$doc->createElement("comm");
        $xml_comm_name=$doc->createElement("name",htmlspecialchars($a));
        $newcomm->appendChild($xml_comm_name);
        $basecomm->appendChild($newcomm);
        }
        $basecomm=$newcomm;
}
}

我的问题是整个 XML 正在正确生成,但值 D 仅显示为 C 的子级,而不是 E 和 F。那么如何修复我的代码来做到这一点?任何帮助表示赞赏。谢谢。

【问题讨论】:

  • 你已经问过stackoverflow.com/questions/46093385/…发生了什么变化?
  • @u_mulder 我问过上一个问题,因为我想知道如何在构建层次结构时命名节点。在这里,我只使用节点内的值,而标签名称保持不变。

标签: php arrays xml dom


【解决方案1】:

您的问题是您没有在父元素的上下文中检查子元素。因此,当您检查 'A-B-E-D'D 时,它只是检查“是否有 D”。它不是在问“父母E是否有D”。所以它认为 D 已经存在。

如果您每次从树的顶部开始时重置有效元素集以检查到正确的父元素,您应该会得到正确的结果。

<?php
    $ip=["A-B-C-D","A-B-E-D","A-B-F-D","G-H","G-B","X-Y-G-B"];

    $doc = new DOMDocument();
    $doc->preserveWhiteSpace = false;
    $doc->formatOutput = true;

    $basecomm = $doc->createElement( "start" );
    $doc->appendChild( $basecomm );

    foreach($ip as $input){
        $base = $doc->getElementsByTagName("comm");
        $currentcomm = $basecomm;

        $arr = explode("-", $input);

        foreach ($arr as $k => $a) {
            $parentComm = null;

            foreach ( $base as $x => $community ) {
                foreach ($community->childNodes as $nextElement) {
                    if ($nextElement->tagName == 'name' && $nextElement->nodeValue==$a) {
                        $parentComm = $nextElement->parentNode;
                    }
                }
            }

            if ($parentComm==null){
                $newcomm=$doc->createElement("comm");
                $xml_comm_name=$doc->createElement("name",htmlspecialchars($a));
                $newcomm->appendChild($xml_comm_name);
                $currentcomm->appendChild($newcomm);
                $base = $newcomm->getElementsByTagName("comm");
                $currentcomm = $newcomm;
            } else {
                $base = $parentComm->getElementsByTagName("comm");
                $currentcomm = $parentComm;
            }
        }
    }

    echo $doc->saveXML();

这是输出,我认为这是您所追求的。

<?xml version="1.0"?>
<start>
  <comm>
    <name>A</name>
    <comm>
      <name>B</name>
      <comm>
        <name>C</name>
        <comm>
          <name>D</name>
        </comm>
      </comm>
      <comm>
        <name>E</name>
        <comm>
          <name>D</name>
        </comm>
      </comm>
      <comm>
        <name>F</name>
        <comm>
          <name>D</name>
        </comm>
      </comm>
    </comm>
  </comm>
  <comm>
    <name>G</name>
    <comm>
      <name>H</name>
    </comm>
    <comm>
      <name>B</name>
    </comm>
  </comm>
  <comm>
    <name>X</name>
    <comm>
      <name>Y</name>
      <comm>
        <name>G</name>
        <comm>
          <name>B</name>
        </comm>
      </comm>
    </comm>
  </comm>
</start>

【讨论】:

  • 嗨,但是如果我要添加另一个数组元素,如“G-H”,这将不起作用。那么作为输出给出的结构是不正确的。
  • 那是因为你用一个新的基础覆盖了$basecomm。如果您保持 $basecomm 应有的状态并使用 $currentcomm 代替它,那么事情应该是正确的。查看更新。
  • 好的,但这又回到了我的第一个问题,如果数组元素是重复的,那么它没有添加到正确的位置。如果最后一个数组元素是“G-B”而不是“G-H”,那么 B 不会再次添加到 G。
  • 基本上你需要将两者结合起来。首先,在其父节点的上下文中检查当前节点。 C-D 和 E-D 是不同的 D。其次,不要覆盖基节点,而是跟踪您正在处理的树的当前部分。
  • 如果您可以尽可能更新代码,将对我和其他阅读此答案的人有所帮助。感谢所有的帮助。
猜你喜欢
  • 2023-04-07
  • 2022-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-30
相关资源
最近更新 更多