Home > database >  Merge duplicate content .xml in php
Merge duplicate content .xml in php

Time:11-09

I am learning the php code. I'm in a situation where it has to be done as soon as possible. Please help me reorganize my xml duplicate data.

original .xml file

<products>
<product>
    <ID>ID1</ID>
    <SKU_parent>SKU1</SKU_parent>
    <SKU>MA</SKU>
    <price>10</price>
    <price-sale>5</price-sale>
    <KHO1>10</KHO1>
    <KHO2>6</KHO2>
    <KHO3>2</KHO3>
</product>
<product>
    <ID>ID2</ID>
    <SKU_parent>SKU2</SKU_parent>
    <SKU>MA2</SKU>
    <price>500</price>
    <price-sale>200</price-sale>
    <KHO1>20</KHO1>
    <KHO2>0</KHO2>
    <KHO3>0</KHO3>
</product>
<product>
    <ID>ID3</ID>
    <SKU_parent>SKU2</SKU_parent>
    <SKU>MA2</SKU>
    <price>500</price>
    <price-sale>200</price-sale>
    <KHO1>0</KHO1>
    <KHO2>30</KHO2>
    <KHO3>0</KHO3>
</product>
<product>
    <ID>ID2</ID>
    <SKU_parent>SKU2</SKU_parent>
    <SKU>MA2</SKU>
    <price>500</price>
    <price-sale>200</price-sale>
    <KHO1>0</KHO1>
    <KHO2>0</KHO2>
    <KHO3>40</KHO3>
</product>

into something like this:

<products>
<product>
    <ID>ID1</ID>
    <SKU_parent>SKU1</SKU_parent>
    <SKU>MA</SKU>
    <price>10</price>
    <price-sale>5</price-sale>
    <KHO1>10</KHO1>
    <KHO2>6</KHO2>
    <KHO3>2</KHO3>
</product>
<product>
    <ID>ID2</ID>
    <SKU_parent>SKU2</SKU_parent>
    <SKU>MA2</SKU>
    <price>500</price>
    <price-sale>200</price-sale>
    <KHO1>20</KHO1>
    <KHO2>30</KHO2>
    <KHO3>40</KHO3>
</product>

I've tried searching on stackoverflow but it doesn't seem to work. I appreciate it when someone help me with this php code

CodePudding user response:

If you're simply using product->ID as the identifier, you could just do:

$xml = new DOMDocument;
$xml->load('dedup.xml');
$xpath = new DOMXpath($xml);
$dupNodes = $xpath->query('/products/product[ID = preceding-sibling::product/ID]');
foreach ($dupNodes as $dupNode) {
    $dupNode->parentNode->removeChild($dupNode);
}
echo $xml->saveXML();

CodePudding user response:

For starters, I converted your XML string into an array.

I reduced your array using SKU_parent as a unique key.

I rebuilt the array again into a XML, using the Francis Lewis function (with some slight modifications, by hardcoding the product node if the array key was numeric) - Source: https://stackoverflow.com/a/19987539/4527645

$xml_string = '<products>
    <product>
        <ID>ID1</ID>
        <SKU_parent>SKU1</SKU_parent>
        <SKU>MA</SKU>
        <price>10</price>
        <price-sale>5</price-sale>
        <KHO1>10</KHO1>
        <KHO2>6</KHO2>
        <KHO3>2</KHO3>
    </product>
    <product>
        <ID>ID2</ID>
        <SKU_parent>SKU2</SKU_parent>
        <SKU>MA2</SKU>
        <price>500</price>
        <price-sale>200</price-sale>
        <KHO1>20</KHO1>
        <KHO2>0</KHO2>
        <KHO3>0</KHO3>
    </product>
    <product>
        <ID>ID3</ID>
        <SKU_parent>SKU2</SKU_parent>
        <SKU>MA2</SKU>
        <price>500</price>
        <price-sale>200</price-sale>
        <KHO1>0</KHO1>
        <KHO2>30</KHO2>
        <KHO3>0</KHO3>
    </product>
    <product>
        <ID>ID2</ID>
        <SKU_parent>SKU2</SKU_parent>
        <SKU>MA2</SKU>
        <price>500</price>
        <price-sale>200</price-sale>
        <KHO1>0</KHO1>
        <KHO2>0</KHO2>
        <KHO3>40</KHO3>
    </product>
    </products>';

$xml = simplexml_load_string($xml_string, 'SimpleXMLElement', LIBXML_NOCDATA);
$json = json_encode($xml);
$xml_array = json_decode($json, true);

$unique = array_reduce($xml_array['product'], function($final, $article){
    static $seen = [];
    if (!array_key_exists($article['SKU_parent'], $seen)) {
        $seen[$article['SKU_parent']] = NULL;
        $final[] = $article;
    }
    return $final;
});

function to_xml(SimpleXMLElement $object, array $data)
{
    foreach ($data as $key => $value) {
        if (is_array($value)) {
            if (is_numeric($key)) {
                $new_object = $object->addChild('product');
            }
            to_xml($new_object, $value);
        } else {
            if ($key != 0 && $key == (int) $key) {
                $key = "key_$key";
            }

            $object->addChild($key, $value);
        }
    }
}

$xml = new SimpleXMLElement('<products/>');
to_xml($xml, $unique);
header('Content-Type: text/xml');
print $xml->asXML();

You can also check a working example of this code here: https://onlinephp.io/c/1d06d

This code eliminates the duplicate product nodes by SKU_parent. In order to merge all the values that are not 0, you have to improve the array_reduce or find another method with array_merge_recursive for example. This is just a starting point.

  • Related