如何控制用 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);
}
}
}
我正在使用 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);
}
}
}