我正在尝试将具有相同结构的多个XML文件合并到一个文件中。
这是我的XML文件的结构:
file1.xml:
<root information="file1">
<items>
<item>FOO</item>
<item>BAR</item>
</items>
</root>
file2.xml:
<root information="file2">
<items>
<item>BAR</item>
<item>FOO</item>
</items>
</root>
使用此代码我已经能够将它们组合在一起:
$files= array(
'file1.xml',
'file2.xml'
);
$dom = new DOMDocument();
$dom->appendChild($dom->createElement('root'));
foreach ($files as $filename) {
$addDom = new DOMDocument();
$addDom->load($filename);
if ($addDom->documentElement) {
foreach ($addDom->documentElement->childNodes as $node) {
$dom->documentElement->appendChild(
$dom->importNode($node, TRUE)
);
}
}
}
$dom->save('output.xml');
这部分工作但删除了原始的根元素,它具有我仍然需要的信息属性。所以我想保留所有现有的根元素,但将它们包装在新的根元素中。这就是我想要的结果:
<files>
<root information="file1">
<items>
<item>FOO</item>
<item>BAR</item>
</items>
</root>
<root information="file2">
<items>
<item>BAR</item>
<item>FOO</item>
</items>
</root>
</files>
但我无法弄清楚如何附加文件。无论我尝试什么,它只会在输出文件的底部结束,而不是附加所有旧的根元素。我猜这很简单,但我无法理解。非常感谢!
答案 0 :(得分:1)
考虑XSLT用于转换XML文件的专用语言。 XSLT维护document()
函数,以便在相对于脚本的路径上从外部文件进行解析。 PHP可以运行带有php-xsl类的XSLT 1.0脚本。请务必在.ini文件中启用此扩展程序。
如果您的文件非常多,例如数百个,请考虑在PHP循环中动态构建XSLT脚本。作为信息,XSLT是一个格式良好的XML文件,因此可以从文件或字符串中进行解析。
XSLT (将.xsl文件保存在与所有XML文件相同的目录中)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<files>
<xsl:copy-of select="root"/>
<xsl:copy-of select="document('file2.xml')/root"/>
<xsl:copy-of select="document('file3.xml')/root"/>
<xsl:copy-of select="document('file4.xml')/root"/>
<!-- add more as needed -->
</files>
</xsl:template>
</xsl:stylesheet>
PHP (加载第一个XML和XSL脚本,然后转换/输出)
// LOAD XML SOURCE
$xml = new DOMDocument('1.0', 'UTF-8');
$xml->load('file1.xml'); // ONLY LOAD FIRST XML
// LOAD XSL SOURCE
$xsl = new DOMDocument('1.0', 'UTF-8');
$xsl->load('XSLT_Script.xsl');
// TRANSFORM XML
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
$newXML = $proc->transformToXML($xml);
// SAVE NEW XML
file_put_contents('Output.xml', $newXML);
答案 1 :(得分:1)
实际上你的来源只有一些小错误。您在目标文档中创建了一个root
文档元素,而不是您示例中的files
元素。另外,源文档中节点的副本是深层次的,您只需要导入它们的文档元素。
我稍微修改了你的代码,使其自包含并修复了错误。
$files= array(
'file1.xml' =>
'<root information="file1">
<items>
<item>FOO</item>
<item>BAR</item>
</items>
</root>',
'file2.xml' =>
'<root information="file2">
<items>
<item>BAR</item>
<item>FOO</item>
</items>
</root>'
);
// create a target document with a files root
$target = new DOMDocument();
$target->appendChild($target->createElement('files'));
// iterate the source files array
foreach ($files as $name => $content) {
// load each source
$source = new DOMDocument();
$source->loadXml($content);
// if it has a document element
if ($source->documentElement) {
// copy it to the target document
$target->documentElement->appendChild(
$target->importNode($source->documentElement, TRUE)
);
}
}
$target->formatOutput = TRUE;
echo $target->saveXml();