获取汇总节点而不是单独的嵌套节点

getting summarized nodes instead of separate nested nodes

我有这样的第三方 xml 文件。这是一个电影应用程序,可以组织在哪个拍摄日拍摄哪个场景。

<schedule>

<DayBreak>
    <AutoText>true</AutoText>
    <Text></Text>
</DayBreak>

<Scene>
    81
</Scene>

<DayBreak>
    <AutoText>false</AutoText>
    <Text>myday</Text>
</DayBreak>

<Scene>
    82
</Scene>

<Scene>
    85
</Scene>

<schedule /> 

如你所见,新的一天,拍摄了第81场景,然后又到了,拍摄了第82场景和第85场景。

(如果你问我,我不会像这样构建 xml,但那是我从其他人那里得到的。)

现在,如果我使用 PHP 的简单 xml 解析这个 xml 文件,我会得到这些数组:

                [DayBreak] => Array
                    (
                        [0] => SimpleXMLElement Object
                            (
                                [AutoText] => true
                                [Text] => SimpleXMLElement Object
                                    (
                                    )

                            )

                        [1] => SimpleXMLElement Object
                            (
                                [AutoText] => false
                                [Text] => myday
                            )
                        )

                [Scene] => Array
                    (
                        [0] => 81
                        [1] => 82
                        [2] => 85
                    )

                [EndShooting] => SimpleXMLElement Object
                    (
                    )

如你所见,随着数组的汇总,我无法再解析哪一天拍摄的场景。

我该怎么办?

谢谢,马特

你试过了吗:

$xml = <<<xml
<schedule>

<DayBreak>
    <AutoText>true</AutoText>
    <Text></Text>
</DayBreak>

<Scene>
    81
</Scene>

<DayBreak>
    <AutoText>false</AutoText>
    <Text>myday</Text>
</DayBreak>

<Scene>
    82
</Scene>

<Scene>
    85
</Scene>

</schedule> 
xml;

$simpleXML = simplexml_load_string ($xml);

foreach ($simpleXML->children() as $node) {
    echo $node->getName().' = '.$node."\n";
}

一种方法是从上到下遍历 schedule 个子节点,沿途修复 XML。当您偶然发现 DayBreak 节点时,在该位置创建一个新的 Day 容器节点并将 DayBreak 放入该 Day 节点。 Scene 后面的节点也将进入该节点。

这样您将拥有更好的工作结构。

<?php
$xml = <<<END
<schedule>

<DayBreak>
    <AutoText>true</AutoText>
    <Text></Text>
</DayBreak>

<Scene>
    81
</Scene>

<DayBreak>
    <AutoText>false</AutoText>
    <Text>myday</Text>
</DayBreak>

<Scene>
    82
</Scene>

<Scene>
    85
</Scene>

</schedule>
END;
// Note: Last line in XML edited (used to be "<schedule />")

// Load
$dom = new DOMDocument();
$dom->loadXml($xml);

// Grab schedule node
$schedule = $dom->getElementsByTagName('schedule')->item(0);

// Loop through the child nodes of schedule
$i = 0;
while ($i < $schedule->childNodes->length) {
    $childNode = $schedule->childNodes->item($i);

    switch ($childNode->nodeName) {
        case 'DayBreak':
            $dayBreak = $childNode;
            // Brand new day. Wrap DayBreak node in Day node, into which the
            // following scene nodes will be moved
            $day = $dom->createElement('Day');
            $schedule->insertBefore($day, $dayBreak);
            $day->appendChild($dayBreak);
            break;

        case 'Scene':
            $sceneNode = $childNode;
            // A scene shot the current day. Move the node into the day node.
            $day->appendChild($childNode);
            continue 2; // Don't increase $i as node was moved out of 'schedule'
    }

    $i++;
}

// echo $dom->saveXML(); // Uncomment to view XML
var_dump(new SimpleXMLElement($dom->saveXML()));

输出:

object(SimpleXMLElement)#5 (1) {
  ["Day"]=>
  array(2) {
    [0]=>
    object(SimpleXMLElement)#6 (2) {
      ["DayBreak"]=>
      object(SimpleXMLElement)#9 (2) {
        ["AutoText"]=>
        string(4) "true"
        ["Text"]=>
        object(SimpleXMLElement)#10 (0) {
        }
      }
      ["Scene"]=>
      string(8) "
    81
"
    }
    [1]=>
    object(SimpleXMLElement)#8 (2) {
      ["DayBreak"]=>
      object(SimpleXMLElement)#9 (2) {
        ["AutoText"]=>
        string(5) "false"
        ["Text"]=>
        string(5) "myday"
      }
      ["Scene"]=>
      array(2) {
        [0]=>
        string(8) "
    82
"
        [1]=>
        string(8) "
    85
"
      }
    }
  }
}

编辑

然后您可以使用 DOMDocument 遍历日期和场景:

foreach ($dom->getElementsByTagName('Day') as $day) {
    echo "Day:";
    foreach ($day->getElementsByTagName('Scene') as $scene) {
        echo ' ' . trim($scene->nodeValue);
    }
    echo PHP_EOL;
}

或简单XML元素对象,如果您更熟悉它:

$xml = new SimpleXMLElement($dom->saveXML());

foreach ($xml->Day as $day) {
    echo "Day:";
    foreach ($day->Scene as $scene) {
        echo ' ' . trim($scene);
    }
    echo PHP_EOL;
}

输出(对于 DOMDocument 和 SimpleXMLElement 示例):

Day: 81
Day: 82 85