Search code examples
phpxmlforeachsimplexml

image name in xml child more than one and get limitation with php


i have xml the other array i got it but first one cant how can i solve this

Xml structure like this and get an error code in xml to php First one is not array the second one is array

i Coudnt get the first image children "sitename/11.jpg"

Xml like this

 [images] => SimpleXMLElement Object ( [image] => Array ( [0] => sitename/15.jpg [1] => sitename/16.jpg [2] => sitename/17.jpg [3] => sitename/18.jpg ) ) )

 [images] => SimpleXMLElement Object ( [image] => sitename/11.jpg ))
<root>
<result>
<node>
<categories>somecategory<categories/>
<images>
<image>sitename/15.jpg</image><image>sitename/16.jpg</image><image>sitename/17.jpg</image><image>sitename/18.jpg</image>
</images>
</node>
<node>
<categories>somecategory<categories/>
<images>
<image>sitename/11.jpg</image>
</images>
</node>
  </result>
      </root>


function solve_something($xml, $destination)
{
    $xml = simplexml_load_file($xml, "SimpleXMLElement", LIBXML_NOCDATA);
    $json = json_encode($xml);
    $items = json_decode($json, TRUE);
    $products = array();
    $product_data = array();
    $row = 1;
foreach ($items['result']['node'] as $item) {
    $product_data['Categories'] = 'categories';
    if (isset($item['images']['image'])) {
        if (is_array($item['images']['image'])) {
            foreach ($item['images']['image'] as $key => $image) {
                $key++;
                if ($key <= 4) {
                    $image_name = 'image' . $key;
                    $product_data[$image_name] = isset($image) ? $image : null;
                }
            }
        } else {
            $product_data['image'] = isset($image) ? $image : null;
        }
    }

$path = createXML($products, $destination);
return $path;
}
The other function code its create the xml file

function createXML($data, $destination)
{

    $xmlDoc = new DOMDocument('1.0', 'UTF-8');
    $root = $xmlDoc->appendChild($xmlDoc->createElement("root"));
    foreach ($data as $key => $product) {

        $productA = $root->appendChild($xmlDoc->createElement('product'));
        foreach ($product as $key1 => $val) {
            if (!empty($val)) {
                if ($key1 == 'price' || $key1 == 'tax' || $key1 == 'stockAmount') {
                    $productA->appendChild($xmlDoc->createElement($key1, $val));
                } else {
                    $ProductKey = $productA->appendChild($xmlDoc->createElement($key1));
                    $ProductKey->appendChild($xmlDoc->createCDATASection($val));
                }
            }
        }
    }
    $xmlDoc->formatOutput = true;
    fn_rm($destination);
    $xmlDoc->save($destination);
    return $destination;
}

Code create

<root>
  <product>
<categories>somecategory<categories/>
<images>
<image1>sitename/15.jpg
<image2>sitename/16.jpg
<image3>sitename/17.jpg
</images>
  </product>
  <product>
<categories>somecategory<categories/>
<images>
<image1>sitename/15.jpg
<image2>sitename/16.jpg
<image3>sitename/17.jpg
<image4>sitename/18.jpg
</images>
  </product>
</root>

But i want

<root>
  <product>
<categories>somecategory<categories/>
<images>
<image1>sitename/15.jpg
<image2>sitename/16.jpg
<image3>sitename/17.jpg
</images>
  </product>
  <product>
<categories>somecategory<categories/>
<images>
<image1>sitename/11.jpg
</images>
  </product>
</root>

Solution

  • There are a few issues with the code

    • If you want to have 3 images, this part if ($key <= 4) { should be lesser or equal than 2.
    • You don't really have to return anything (or you want to check for false), as you are writing a file, as the save function returns the number of bytes written or false if an error occurred.
    • Using $key++; like this in the foreach can also be done using a for loop where you can use $i to append after image
    • Not sure why you want to use createCDATASection but I have left that part out to get the desired result
    • As you have multiple sections of node, you may use an $product_data array per iteration to add the values to and after the foreach add $product_data to the $products array to prevent overwriting the values for every loop.

    The updated code might look like

    function solve_something($xml, $destination)
    {
        $xml = simplexml_load_string($xml, "SimpleXMLElement", LIBXML_NOCDATA);
        $json = json_encode($xml);
        $items = json_decode($json, TRUE);
        $products = array();
    
        foreach ($items['result']['node'] as $item) {
            $product_data = array();
            $category = $item["categories"];
            $product_data["categories"] = $category;
            if (isset($item['images']['image'])) {
                if (is_array($item['images']['image'])) {
                    for ($i = 0; $i < count($item['images']['image']); $i++) {
                        if ($i < 3) $product_data["image" . ($i + 1)] = $item['images']['image'][$i];
                    }
                } else $product_data["image1"] = $item['images']['image'];
            }
            $products[] = $product_data;
        }
        createXML($products, $destination);
    }
    
    function createXML($data, $destination)
    {
        $xmlDoc = new DOMDocument('1.0', 'UTF-8');
        $root = $xmlDoc->appendChild($xmlDoc->createElement("root"));
    
        foreach ($data as $key => $product) {
            $productA = $root->appendChild($xmlDoc->createElement('product'));
            $imagesElm = $xmlDoc->createElement('images');
            foreach ($product as $key1 => $val) {
                if ($key1 == 'price' || $key1 == 'tax' || $key1 == 'stockAmount' || $key1 === "categories") {
                    $productA->appendChild($xmlDoc->createElement($key1, $val));
                } elseif (substr($key1, 0, 5) === "image") {
                    $imagesElm->appendChild($xmlDoc->createElement($key1, $val));
                }
            }
            $productA->appendChild($imagesElm);
        }
    
        $xmlDoc->formatOutput = true;
        $xmlDoc->save($destination);
    }
    
    $xml = <<<XML
    <?xml version="1.0" encoding="utf-8"?>
    <root>
        <result>
            <node>
                <categories>somecategory</categories>
                <images>
                    <image>sitename/15.jpg</image>
                    <image>sitename/16.jpg</image>
                    <image>sitename/17.jpg</image>
                    <image>sitename/18.jpg</image>
                </images>
            </node>
            <node>
                <categories>somecategory</categories>
                <images>
                    <image>sitename/11.jpg</image>
                </images>
            </node>
        </result>
    </root>
    XML;
    
    solve_something($xml, "result.xml");
    

    The xml in result.xml looks like

    <?xml version="1.0" encoding="UTF-8"?>
    <root>
      <product>
        <categories>somecategory</categories>
        <images>
          <image1>sitename/15.jpg</image1>
          <image2>sitename/16.jpg</image2>
          <image3>sitename/17.jpg</image3>
        </images>
      </product>
      <product>
        <categories>somecategory</categories>
        <images>
          <image1>sitename/11.jpg</image1>
        </images>
      </product>
    </root>