合并两个带有参考ID的XML文件

时间:2018-07-28 20:48:33

标签: php xml

我有两种XML,有人可以帮助我如何将其与PHP合并为一种XML。 两种XML具有相同的。我需要将其与所有节点合并,并使用相同的“ ProductCode”引用数据。

内容XML1:

<Table>
<ProductCode>0352097</ProductCode>
<ProductName>Product Name</ProductName>
<ProductType>Product Type</ProductType>
<Brand>Brand</Brand>
<PartNo>Q3960A</PartNo>
</Table>

内容XML2:

<Table>
<ProductCode>0120392</ProductCode>
<ProductListPrice>XXX</ProductListPrice>
<ProductDiscount>YYYY</ProductDiscount>
<ProductPartnerPrice>ZZZ</ProductPartnerPrice>
</Table>

我要完成这个:

<Table>
<ProductCode>0352097</ProductCode>
<ProductName>Product Name</ProductName>
<ProductType>Product Type</ProductType>
<Brand>Brand</Brand>
<PartNo>Q3960A</PartNo>
<ProductListPrice>XXX</ProductListPrice>
<ProductDiscount>YYYY</ProductDiscount>
<ProductPartnerPrice>ZZZ</ProductPartnerPrice>
</Table>

4 个答案:

答案 0 :(得分:0)

您可以使用simplexml_load_string函数和SimpleXMLElement类来处理XML。

代码段

$xml1 = '<Table>
<ProductCode>0352097</ProductCode>
<ProductName>Product Name</ProductName>
<ProductType>Product Type</ProductType>
<Brand>Brand</Brand>
<PartNo>Q3960A</PartNo>
</Table>';

$xml2 = '<Table>
<ProductCode>0120392</ProductCode>
<ProductListPrice>XXX</ProductListPrice>
<ProductDiscount>YYYY</ProductDiscount>
<ProductPartnerPrice>ZZZ</ProductPartnerPrice>
</Table>';

//Converting to array
$xml1 = (array) simplexml_load_string($xml1);
$xml2 = (array) simplexml_load_string($xml2);
array_shift($xml2); //Removing Product Code From Second XML
//Merging Together
$resultAsArray =  array_merge($xml1, $xml2);
//Flipping array
$flipped = array_flip($resultAsArray);

//Converting Back To The XML
$resultXML = new SimpleXMLElement('<Table/>');
array_walk($flipped, array ($resultXML, 'addChild'));
print $resultXML->asXML();

输出

<?xml version="1.0"?>
<Table>
   <ProductCode>0352097</ProductCode>
   <ProductName>Product Name</ProductName>
   <ProductType>Product Type</ProductType>
   <Brand>Brand</Brand>
   <PartNo>Q3960A</PartNo>
   <ProductListPrice>XXX</ProductListPrice>
   <ProductDiscount>YYYY</ProductDiscount>
   <ProductPartnerPrice>ZZZ</ProductPartnerPrice>
</Table>

检查演示Here

参考:
simplexml_load_string
SimpleXMLElement

答案 1 :(得分:0)

使用SimpleXML处理文档是最简单的选择。假定您有两个要合并的零件列表,并使用XPath在第一个文档中找到匹配的数据,并使用零件从第二个文档中进行更新。然后,它将所有内容(除了ProductCode除外)都复制到基本文档中。

所以有一些简单的测试数据...

$xml1 = "<Products>
    <Table>
        <ProductCode>0352097</ProductCode>
        <ProductName>Product Name</ProductName>
        <ProductType>Product Type</ProductType>
        <Brand>Brand</Brand>
        <PartNo>Q3960A</PartNo>
    </Table>
    <Table>
        <ProductCode>0352098</ProductCode>
        <ProductName>Product Name2</ProductName>
        <ProductType>Product Type2</ProductType>
        <Brand>Brand2</Brand>
        <PartNo>Q3960A2</PartNo>
    </Table>
</Products>";

$xml2 = "<Products>
    <Table>
        <ProductCode>0352097</ProductCode>
        <ProductListPrice>p1</ProductListPrice>
        <ProductDiscount>pp1</ProductDiscount>
        <ProductPartnerPrice>1</ProductPartnerPrice>
    </Table>
    <Table>
        <ProductCode>0352098</ProductCode>
        <ProductListPrice>p2</ProductListPrice>
        <ProductDiscount>pp2</ProductDiscount>
        <ProductPartnerPrice>2</ProductPartnerPrice>
    </Table>
</Products>";

代码归结为...

$base = simplexml_load_string($xml1);
$add = simplexml_load_string($xml2);

foreach ( $add->Table as $addData )    {
    // Find the corresponding element (take the first match using [0])
    $addTo = $base->xpath("//Table[ProductCode='{$addData->ProductCode}']")[0];
    foreach ( $addData->children() as $name => $value )    {
        if ($name != "ProductCode") {
            $addTo->addChild($name, $value);
        }
    }
}

echo $base->asXML();

请注意,这仅适用于平面结构,如果您具有任何属性或更复杂的数据结构,则需要使用其他解决方案。

答案 2 :(得分:0)

DOM使您可以将节点从一个文档导入到另一个文档中,并且可以使用Xpath选择节点。

$target = new DOMDocument();
$target->preserveWhiteSpace = FALSE;
$target->loadXml($xml1);
$targetXpath = new DOMXpath($target);

$source = new DOMDocument();
$source->loadXml($xml2);
$sourceXpath = new DOMXpath($source);
foreach ($targetXpath->evaluate('//Table') as $tableNode) {
  $productCode = $targetXpath->evaluate('string(ProductCode)', $tableNode);
  foreach ($sourceXpath->evaluate('//Table[ProductCode="'.$productCode.'"]/*[not(self::ProductCode)]') as $node) {
    $tableNode->appendChild(
      $target->importNode($node, TRUE)
    );
  }
}

$target->formatOutput = TRUE;
echo $target->saveXml();

DOMDocument::importNode()复制包含其所有属性(标记名称,名称空间),属性和后代节点的节点。

答案 3 :(得分:-1)

应该是这样,您应该安装了php-xml:

$myXMLData = "
    <struct>
    <Table>
    <ProductCode>0352097</ProductCode>
    <ProductName>Product Name</ProductName>
    <ProductType>Product Type</ProductType>
    <Brand>Brand</Brand>
    <PartNo>Q3960A</PartNo>
    </Table>
    <Table>
    <ProductCode>0352097</ProductCode>
    <ProductName>Product Name</ProductName>
    <ProductType>Product Type</ProductType>
    <Brand>Brand</Brand>
    <PartNo>Q3960A</PartNo>
    </Table>
    <Table>
    <ProductCode>0352097</ProductCode>
    <ProductName>Product Name</ProductName>
    <ProductType>Product Type</ProductType>
    <Brand>Brand</Brand>
    <PartNo>Q3960A</PartNo>
    </Table>
    </struct>";

    $myXMLData2 = "
    <struct>
    <Table>
    <ProductCode>0120392</ProductCode>
    <ProductListPrice>XXX</ProductListPrice>
    <ProductDiscount>YYYY</ProductDiscount>
    <ProductPartnerPrice>ZZZ</ProductPartnerPrice>
    </Table>
    <Table>
    <ProductCode>0352097</ProductCode>
    <ProductListPrice>XXX</ProductListPrice>
    <ProductDiscount>YYYY</ProductDiscount>
    <ProductPartnerPrice>ZZZ</ProductPartnerPrice>
    </Table>
    </struct>";

    $xml = simplexml_load_string($myXMLData);
    $xml2 = simplexml_load_string($myXMLData2);
    // Converting SimpleXML object to an array, it's odd but fast way
    $xml = json_decode(json_encode((array)$xml), TRUE);
    $xml2 = json_decode(json_encode((array)$xml2), TRUE);

    function merge(array $left, array $right, $id)
    {
        $result = [];
        $leftIndex = 0;
        $rightIndex = 0;

        do {
            if ($leftIndex < count($left)) {
                $key = array_search($left[$leftIndex][$id], array_column($right, $id));
                $result[$left[$leftIndex][$id]] = array_merge($left[$leftIndex], $right[$key]);
                $leftIndex++;
            } elseif($rightIndex < count($right)) {
                if (isset($result[$right[$rightIndex][$id]])) {
                    $rightIndex++;
                    continue;
                }
                $key = array_search($right[$rightIndex][$id], array_column($right, $id));
                $result[$right[$rightIndex][$id]] = array_merge($right[$rightIndex], $right[$key]);
                $rightIndex++;
            }
        } while ($leftIndex < count($left) || $rightIndex < count($right));

        return $result;
    }

    print_r(merge($xml['Table'], $xml2['Table'], 'ProductCode'));