2

I have an XML file in which one child has two categories, but with the same name. I want to add one title to each one. How can we do it in PHP?

This is my XML

<root>
    <result>
        <node>
            <title> Some Title Name</title>
                <categories>
                    <category> categor_one </category>
                    <category> categor_two </category>
                </categories>
        </node>

        <node>
            <title> Some Title Name</title>
            <categories>
                <category> categor_one </category>
                <category> categor_tree </category>
            </categories>
        </node>
    </result>
</root>

But I want to obtain this

<root>
    <result>
        <node>
            <title> Some Title Name</title>
            <category>categor_one///categor_two </category>
            <category1>categor_one///categor_tree</category1>
        </node>
    </result>
</root>

I managed to impement a function that only gets correctly the category, but if the title is the same it doesn't work as it just creates a new one.

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();

    foreach($items['result']['node'] as $item){
        $product_data['title'] = $item['title'];
        foreach ($item['categories'] as $category) {
            if (is_array($category)) {
                $product_data['category'] = implode('///', $category);
            } else {
                $product_data['category'] = $category;
            }
        }
        $products[] = $product_data;
        unset($product_data);
    }
    $path = createXML($products, $destination);
    return $path;

}

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;
}

The output of my code is something like this

    <root>
        <product>
            <title> Some Title Name</title>
            <category>categor_one///categor_two </category>
        </product>
        <product>
            <title> Some Title Name</title>
                <category>categor_one///categor_tree</category>
         </product>
     </root>
crazyshark
  • 55
  • 5

1 Answers1

0

If you want to keep the data together with the same title, one approach could be to collect that data upfront by using the title as an array key (if it is a valid array key)

When you create the xml, you have the title in the outer foreach loop as the key, and in the inner foreach you can create elements using implode.

Note that in your code you started using product so I took that as a node name.

Example code, which you could use in your code:

$products = array();
$product_data = array();
$xml = simplexml_load_file($xml, "SimpleXMLElement", LIBXML_NOCDATA);

foreach ($xml->result->node as $node) {
    $product_data['title'] = (string)$node->title;
    foreach($node->categories as $category) {
        if (is_array($category)) {
            $product_data['category'] = implode('///', $category);
            continue;
        } 
        $product_data['category'] = (array)$category->category;        
    }
    $products[(string)$node->title][] = $product_data;
}

$xmlDoc = new DOMDocument('1.0', 'UTF-8');
$root = $xmlDoc->appendChild($xmlDoc->createElement("root"));
foreach ($products as $key => $product) {
    $productA = $root->appendChild($xmlDoc->createElement('product'));
    $productA->appendChild($xmlDoc->createElement("title", $key));
    for ($i = 0; $i < count($product); $i++) {        
        $productA->appendChild($xmlDoc->createElement("category" . $i, implode("///", $product[$i]["category"])));
    }
}
$xmlDoc->formatOutput = true;
echo $xmlDoc->saveXML();

Output

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <product>
    <title> Some Title Name</title>
    <category0> categor_one /// categor_two </category0>
    <category1> categor_one /// categor_tree </category1>
  </product>
</root>

Php demo

The fourth bird
  • 154,723
  • 16
  • 55
  • 70