skip to Main Content

I have 2 XML files for importing products to Woocommerce. Products in both files have the same ID. The only difference is the price field between two XML files.
The first XML is something like this:

<products>
 <product>
  <product_id>14201</product_id>
  <title>some title</title>
  <image>some image</image>
  <price>10</price>
  <category>some category</category>
 </product>
</products>

and the second XML file is something like this:

<products>
 <product>
  <product_id>14201</product_id>
  <title>some title</title>
  <image>some image</image>
  <sale_price>7</sale_price>
  <category>some category</category>
 </product>
</products>

i want a result like this:

<products>
 <product>
  <product_id>14201</product_id>
  <title>some title</title>
  <image>some image</image>
  <price>10</price>
  <sale_price>7</sale_price>
  <category>some category</category>
 </product>
</products>

how i can merge all the fields from first XML and only the <sale_price> field from the second XML with PHP simplexml_load_file()?

this is my PHP script:

<?php
$xml = simplexml_load_file("https://mywebsite.com/xmlfile.xml");

echo "<?xml version="1.0" encoding="UTF-8"?><products>";

foreach ($xml->products->product as $prod) {
$pid = $prod->product_id;
$category = $prod->category;
$title = $prod->title;
$image = $prod->image;
$price = $prod->price;

?>
<product>
 <id><?php echo $pid;?></id>
 .....
 .....
</product>
<?php
}
echo "</products>";
?>

2

Answers


  1. You could use XPath to match the product id in the second file, but this could mean re-running a query each product.

    This code first reads the second file and extracts all of the sale prices and indexes them by the product id. Then it reads the first file and adds in the sale price when there is a match form the stored array…

    $sale = simplexml_load_file("b.xml");
    $salePrices = [];
    foreach ( $sale->product as $product )  {
        $salePrices[(string)$product->product_id] = (string)$product->sale_price;
    }
    
    $xml = simplexml_load_file("a.xml");
    $key = 0;
    foreach ( $xml->product as $product )   {
        if ( isset($salePrices[(string)$product->product_id]))  {
            $xml->product[$key]->sale_price = $salePrices[(string)$product->product_id];
        }
        $key++;
    }
    
    echo $xml->asXML();
    

    (Change file names as required)

    Login or Signup to reply.
  2. I would also go with xpath and just query the update values from the second file for the first one. Example with strings, replace the simple_load function to fit your needs.

    Throws in case XML does not parse.

    May get bogus results in case product_id evaluates to a different integer value (e.g. empty to 0 and there is a product with the id 0).

    foreach (($aXml = simplexml_load_string($a))->xpath(
        '/*/product'
    ) as $p)
        foreach (simplexml_load_string($b)->xpath(
            sprintf('/*/%s[./product_id = %d]/sale_price', $p->getName(), $p->product_id)
        ) as $u)
            $p->{$u->getName()} = $u
            ;
    

    Example on 3v4l.org: https://3v4l.org/XStUe

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search