'XML to CSV with PHP converter [problem with images grabing]

I really need your help who works with XML and PHP. Looked for many other questions, but still nothing was found about my situation when in xml there is deeper fields and I can't grab them to csv output (code below).

<product>
<images>
<image>...</image>
<image>...</image>
</images>
</product>

My XML file looks like this:

<root>
<product>
<url>
<![CDATA[
https://
]]>
</url>
<id>185</id>
<barcode>284</barcode>
<categories>
<category>14</category>
<category>2</category>
</categories>
<title>
<![CDATA[ Product1 ]]>
</title>
<description>
<![CDATA[
<p>description</p>
]]>
</description>
<price>10</price>
<sec_costs>13.000000</sec_costs>
<quantity>10</quantity>
<warranty/>
<weight>0.000000</weight>
<delivery_text>
<![CDATA[ 1 - 2 d. ]]>
</delivery_text>
<manufacturer>
<![CDATA[ ]]>
</manufacturer>
<images>
        <image>
<![CDATA[
https://test.eu/r.jpg
]]>
       </image>
        <image>
<![CDATA[
https://test.eu/er.jpg
]]>
       </image>
        <image>
<![CDATA[
https://test.eu/eer.jpg
]]>
       </image>
</images>
<product_with_gift>
<![CDATA[ False ]]>
</product_with_gift>
<barcode_format>
<![CDATA[ EAN ]]>
</barcode_format>
</product>

I am using this code to convert it from XML to CSV (used it from other member), the problem is the code works fine, but it doesn't grab images (tried replacing image with images, added extra images columns, but nothing worked out, it just doesn't grab links to image files:

<?
$filexml = 'imp2.xml';
$xml = simplexml_load_file($filexml);
$xml->registerXPathNamespace('g', 'http://base.google.com/ns/1.0');

if (file_exists($filexml))  {    
   $xml = simplexml_load_file($filexml);
   $i = 1;           // Position counter
   $values = [];     // PHP array

   // Writing column headers
   $columns = array('id', 'barcode', 'title', 'description', 'price', 'sec_costs', 'quantity', 'warranty', 'weight', 'delivery_text', 'manufacturer', 'image', 'product_with_gift', 'barcode_format');

   $fs = fopen('csv.csv', 'w');
   fputcsv($fs, $columns);      
   fclose($fs);

   // Iterate through each <product> node
   $node = $xml->xpath('//product');

   foreach ($node as $n) {               
       // Iterate through each child of <item> node
       foreach ($columns as $col) {         
           if (count($xml->xpath('//product['.$i.']/'.$col)) > 0) {
              $values[] = trim($xml->xpath('//product['.$i.']/'.$col)[0]);
           } else {
              $values[] = '';
           }    
       }    
       // Write to CSV files (appending to column headers)
       $fs = fopen('csv.csv', 'a');
       fputcsv($fs, $values);      
       fclose($fs);  

       $values = [];    // Clean out array for next <item> (i.e., row)
       $i++;            // Move to next <item> (i.e., node position)
   }
}
?>

Any solutions from mid, premium xml,php?



Solution 1:[1]

The problem is that you are trying to fetch a list of nodes using just the images tag as the start point, as the subnodes have their own content, they will not appear in the higher level nodes text.

I've made a few changes to the code, but also I now use the <image> element to fetch the data. This code doesn't assume it's just one node for each item, so when it uses the XPath, it always loops through all items and build them into a single string before adding them to the CSV.

$filexml = 'imp2.xml';

if (file_exists($filexml))  {
    // Only open file once you know it exists
    $xml = simplexml_load_file($filexml);
    $i = 1;           // Position counter
    $values = [];     // PHP array

    // Writing column headers
    $columns = array('id', 'barcode', 'title', 'description', 'price', 'sec_costs', 'quantity', 'warranty', 'weight', 'delivery_text', 'manufacturer', 'image', 'product_with_gift', 'barcode_format');

    // Open output file at start
    $fs = fopen('csv.csv', 'w');
    fputcsv($fs, $columns);

    // Iterate through each <product> node
    $node = $xml->xpath('//product');

    foreach ($node as $n) {
        // Iterate through each child of <item> node
        foreach ($columns as $col) {
            // Use //'.$col so node doesn't have to be directly under product
            $dataMatch = $xml->xpath('//product['.$i.']//'.$col);
            if (count($dataMatch) > 0) {
                // Build list of all matches
                $newData = '';
                foreach ( $dataMatch as $data)  {
                    $newData .= trim((string)$data).",";
                }
                // Remove last comma before adding it in
                $values[] = rtrim($newData, ",");
            } else {
                $values[] = '';
            }
        }
        fputcsv($fs, $values);

        $values = [];    // Clean out array for next <item> (i.e., row)
        $i++;            // Move to next <item> (i.e., node position)
    }
    // Close file only at end
    fclose($fs);
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Nigel Ren