如何通过ID合并两个xml文件(第一个作为子节点值,第二个作为属性)

时间:2019-05-09 08:51:43

标签: php xml

我有两个具有这种结构的XML文件:

first.xml

<items>
    <item>
        <id>foo</id>
        <desc>lorem ipsum</desc>
    </item>
    <item>
        <id>boo</id>
        <desc>lorem ipsum</desc>
    </item>
</items>

second.xml

<item_list>
    <item id="foo">
        <stock_quantity>20</stock_quantity>
    </item>
    <item id="boo">
        <stock_quantity>11</stock_quantity>
    </item>
</item_list>

并且我需要通过id组合它们,以便输出文件看起来像这样:

output.xml

<items>
    <item>
        <id>foo</id>
        <desc>lorem ipsum</desc>
        <stock_quantity>20</stock_quantity>
    </item>
    <item>
        <id>boo</id>
        <desc>lorem ipsum</desc>
        <stock_quantity>11</stock_quantity>
    </item>
</items>

我需要使用PHP和XML DOMDocument。你有办法吗?

3 个答案:

答案 0 :(得分:0)

您可以使用simplexml库来实现这一目标,

// loading xml to object from file
$xml1 = simplexml_load_file("first.xml") or die("Error: Cannot create object");
$xml2 = simplexml_load_file("second.xml") or die("Error: Cannot create object");
// its core xml iterator for simplexml library
foreach ($xml1->children() as $items1) {
    $id = trim($items1->id); // trim to check with id matched in 2.xml
    foreach ($xml2->children() as $items2) { // iterating children of 2.xml
        if ($items2[0]['id'] == $id) { // simply checking attribute of id in 2.xml with 1.xml's id value
            foreach ($items2 as $key => $value) {
                $items1->addChild($key, (string) ($value)); // adding children to 1.xml object
            }
        }
    }
}
$xml1->asXml('output.xml'); // generating https://www.php.net/manual/en/simplexmlelement.asxml.php

答案 1 :(得分:0)

使用DOMDocument并具有将节点从一个文档复制到另一个文档的功能,使您可以将库存中的节点直接插入到主要XML。

表达式//item[@id='boo']/stock_quantity表示在<stock_quantity>元素中找到具有属性的<item>元素,而不是循环查找匹配的记录,而是使用XPath搜索匹配的记录。的id='boo'

$main = new DOMDocument();
$main->load("main.xml");
$add = new DOMDocument();
$add->load("stock.xml");
$searchAdd = new DOMXPath($add);

// Find the list of items
$items = $main->getElementsByTagName("item");
foreach ( $items as $item ) {
    // Exract the value of the id node
    $id = $item->getElementsByTagName("id")[0]->nodeValue;
    // Find the corresponding node in the stock file
    $stockQty = $searchAdd->evaluate("//item[@id='{$id}']/stock_quantity");
    // Import the <stock_quantity> node (and all contents)
    $copy = $main->importNode($stockQty[0], true);
    // Add the imported node
    $item->appendChild($copy);
}

echo $main->saveXML();

答案 2 :(得分:0)

请考虑XSLT,这是一种专用语言(如SQL),旨在转换XML文件,例如您的特定最终用途需求。与许多通用语言一样,PHP可以使用特殊的库php-xsl类(需要启用.ini扩展名)将XSLT 1.0作为较低层运行。

XSLT (另存为.xsl文件,一个特殊的.xml文件;以下假定同一目录中有第二个XML)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <!-- IDENTITY TRANSFORM -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- ADD NODE BY CORRESPONDING id VALUE -->
  <xsl:template match="item">
    <xsl:copy>
      <xsl:variable name="curr_id" select="id"/>
      <xsl:apply-templates select="@*|node()"/>
      <xsl:copy-of select="document('second.xml')/item_list/item[@id = $curr_id]/*"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

PHP (仅引用第一个XML)

// Load the XML source and XSLT file
$xml = new DOMDocument;
$xml->load('first.xml');

$xsl = new DOMDocument;
$xsl->load('XSLTScript.xsl');

// Configure transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);

// Transform XML source
$newXML = new DOMDocument;
$newXML = $proc->transformToXML($xml);
echo $newXML;

// Save output to file
$xmlfile = 'output.xml';
file_put_contents($xmlfile, $newXML);