【问题标题】:Combine multiple XML files with PHP and wrap in new root element将多个 XML 文件与 PHP 组合并包装在新的根元素中
【发布时间】:2017-06-07 14:39:15
【问题描述】:

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

但我不知道如何附加文件。无论我尝试什么,它都只会出现在输出文件的底部,而不是附加所有旧的根元素。我猜这很简单,但我就是想不通。非常感谢您的帮助!

【问题讨论】:

  • 为什么要使用DOMDocument 而不是直接将它们附加到新文件中?
  • 为什么要麻烦 XML 处理?只需回显您的开始标签,转储文件,回显您的结束标签。

标签: php xml


【解决方案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();

【讨论】:

  • 谢谢!让它像魅力一样工作。不得不使用 load 而不是 loadXml,由于某种原因,否则它将无法工作。还必须在新的 DOMDocument 之后指定字符集,因为我的源文件是一些我无法控制的可怕的 windows-1252 格式。
【解决方案2】:

考虑XSLT 设计用于转换XML 文件的专用语言。 XSLT 维护document() 函数以从相对于脚本的路径中的外部文件进行解析。 PHP 可以使用其php-xsl 类运行XSLT 1.0 脚本。请务必在 .ini 文件中启用此扩展名。

如果您的文件非常多(例如数百个),请考虑在 PHP 循环中动态构建 XSLT 脚本。作为信息,XSLT 是一个格式良好的 XML 文件,因此可以从文件或字符串中解析出来。

XSLT (与所有 XML 文件在同一目录中保存为 .xsl 文件)

<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);

【讨论】:

    猜你喜欢
    • 2016-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-04
    相关资源
    最近更新 更多