如何控制用 PHP 创建的 XML 中元素的顺序?

How to control order of elements in XML created with PHP?

我正在使用 PHP 生成一个 XML 文档,并且元素必须按特定顺序排列。他们中的大多数工作正常,除了三个。子元素如下所示:

  <p>
    <co>ABC</co>
    <nbr>123456</nbr>
    <name>short product description</name>
    <desc>long product description</desc>
    <kw>searchable keywords</kw>
    <i-std>relative/path/to/image</i-std>
    <i-lg>relative/path/to/large/image</i-lg>
    <i-thmb>relative/path/to/thumbnail</i-thmb>
    <mfg>manufacturer</mfg>
    <a-pckCont>package contents</a-pckCont>
</p>

我使用的代码工作正常,但三个图像元素顺序不对,这使得使用它们的内容处理器出现故障。我最近尝试的最多的是:

$newStd = 0;
foreach ($items as $row => $innerArray) {
    $p = $domTree->createElement('p');
    $xmlRoot->appendChild($p);
    foreach ($innerArray as $innerRow => $value) {
        if ($innerRow != 'key') {
            if ($value != '') {
                echo $innerRow . ' : ' . $value . '<br />';
                if ($innerRow == 'i-std') {
                    $newStd = $domTree->createElement($innerRow, htmlspecialchars($value));
                } else {
                    $p->appendChild($domTree->createElement($innerRow, htmlspecialchars($value)));
                }
            }
        }
        if ($newStd != 0) {
            $thmb = $p->getElementsByTagName('i-thmb')->item(0);
            $p->insertBefore($newStd, $thmb);
        }
    }
}

我的想法是让它在使用 InsertBefore 写入元素之前先写出所有子元素,以确保它出现在 i-thmb 元素之前,但这并没有什么不同。无论我做什么,我得到的输出都是按照 i-thmb、i-std、i-lg 的顺序排列的。在重新排列用于构建 XML 文档的数组中的一些变量后,所有其他元素以正确的顺序出现。我还没有尝试控制 i-lg 元素,因为 i-std 不工作。

最终,这将用于将 XML 文档组合在一起,但在测试以确保 XML 处理器不会阻塞时,我发现根本问题是元素的顺序在很大程度上决定了它是否有效(至少可以说,我正在使用的系统没有记录并且支持很差)。

编辑添加:像我在内部 foreach 循环中所做的那样回显以正确的顺序显示它们,但它们在输出文件中是乱序的。

我认为一些更改会使代码更健壮(我已经为代码添加了注释以了解具体细节)。这里主要涉及数据类型的检查和每次循环中重置替换字段...

foreach ($items as $row => $innerArray) {
    $p = $domTree->createElement('p');
    $xmlRoot->appendChild($p);
    foreach ($innerArray as $innerRow => $value) {
        $newStd = 0;    // Make sure this is set each time
        if ($innerRow != 'key') {
            if ($value != '') {
                echo $innerRow . ' : ' . $value . '<br />';
                if ($innerRow == 'i-std') {
                    $newStd = $domTree->createElement($innerRow, htmlspecialchars($value));
                } else {
                    $p->appendChild($domTree->createElement($innerRow, htmlspecialchars($value)));
                }
            }
        }
        // Check if a replacement element, checking type of element
        if ($newStd instanceof DOMElement) {
            $thmb = $p->getElementsByTagName('i-thmb')->item(0);
            $p->insertBefore($newStd, $thmb);
        }
    }
}