将多个XML文件与PHP组合并包装在新的根元素中

时间:2017-06-07 14:39:15

标签: php xml

我正在尝试将具有相同结构的多个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>

但我无法弄清楚如何附加文件。无论我尝试什么,它只会在输出文件的底部结束,而不是附加所有旧的根元素。我猜这很简单,但我无法理解。非常感谢!

2 个答案:

答案 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();