Miloš Miljković
Miloš Miljković

Reputation: 497

Construct an xml file from a php array

Inside a for loop I have the following code which pushes an array that contains some data inside another array:

$finCombo = array("color" => $color, "size" => $size, "productID" => $theProductID."-".$color, "imageURL" => 'https://click-tshirt.gr/images/detailed/all/'.$theProductCode."_".strtolower($color).'.jpg', "productURL" => $theProductURL, "title" => $theProductName, "price" => $theProductPrice, "category_path" => $theCategoryName, "availability" => $theProductAvailability, "brand" => $theProductBrand, "SKU" => $theProductCode."-".$color);

array_push($finalCmb, $finCombo);

The goal is to create an XML file using the data from the array. The code should return an xml file that looks like the below example:

<store>
    <date>2017-09-22 19:30</date>
    <products>
         <product>
             <SKU>10206-BLACK</SKU>
             <productID>338-BLACK</productID>
             <size>Small, Medium, Large, X Large</size>
             <color>BLACK</color>
             <title>Women's Jersey Short Sleeve Deep V-Neck Tee BLACK</title>
             <productURL>https://click-tshirt.gr/el-4/t-shirt-el/womens-jersey-short-sleeve-deep-v-neck-tee/</productURL>
             <imageURL>https://click-tshirt.gr/images/detailed/all/10206_Black.jpg</imageURL>
             <price>9.90</price>
             <category_path>ΓΥΝΑΙΚΕΙΑ///T-SHIRT</category_path>
             <brand>BELLA&CANVAS</brand>
             <availability>Κατόπιν παραγγελίας</availability>
         </product>

Here an example of the array where you can see that "425-DEEP_NAVY" is inserted in the array with the size "Medium" but later on it is inserted again and again for each size:

Array ( [0] => Array ( [0] => Array ( [color] => BLACK_DARK_GREY [size] => Small [productID] => 390-BLACK_DARK_GREY [imageURL] => https://click-tshirt.gr/images/detailed/all/18608_black_dark‌​_grey.jpg [productURL] => http://click-tshirt.gr/el-3/category-50/adult-fashion-basic-‌​ls-hooded-tee/ [title] => Adult Fashion Basic LS Hooded Tee [price] => 13.800000 [category_path] => ΑΝΔΡΙΚΑ/ΦΟΥΤΕΡΑΚΙΑ ΜΕ ΚΟΥΚΟΥΛΑ [availability] => Κατόπιν παραγγελίας [brand] => ANVIL [SKU] => 18608-BLACK_DARK_GREY )))

There is also one thing that happens and so far I have managed to resolve it with JavaScript. That is the products are inserted in the array for every "productID" there is several "size's" so for each size the same productID is inserted several times while what I need is that for each productID the size to be an array containing all sizes that correspond to that productID. See codepen console below:

codepen example

Upvotes: 0

Views: 1661

Answers (1)

Xyz
Xyz

Reputation: 6013

Combining arrays

First, your problem probably lies in your usage of array_push.

$array = ['test'];
$secondarray = ['foo', 'bar'];

array_push($array, $secondarray);

will give you an $array containing the array $secondarray

Array (
    0 => (string) "test"
    1 => Array (
        0 => (string) "foo"
        1 => (string) "bar"
    )
)

What I guess you want is array_merge(), which will merge the two arrays instead.

$array = ['test'];
$secondArray = ['foo', 'bar'];
$resultArray = array_merge($array, $secondArray);

Which will give you the $resultArray:

Array(
    [1] => (string) "test"
    [2] => (string) "foo"
    [3] => (string) "bar"
)

Converting to XML

You can do this in multiple ways. Write your own solution using XmlWriter or create a DOM structure using either SimpleXml or DomDocument.

SimpleXml

Perhaps the simplest solution is to use SimpleXmlElement like this:

$xml = SimpleXmlElement('<store/>');
$xml->addChild('date', '2017-09-22 19:30');
$products = $xml->addChild('products');
$product  = $products->addChild('product');
foreach ($finCombo as $name => $value) {
    $product->addChild($name, $value);
}
echo $xml->asXML(), PHP_EOL;

SimpleXml with Formatting

If you want to use the same formatting/indentation as in your example, you need to use DomDocument or XmlWriter. If you are already doing this in SimpleXml, you can easily load a DomDocument from a SimpleXmlElement.

...
$domxml = new DOMDocument('1.0');
$domxml->preserveWhiteSpace = false;
$domxml->formatOutput = true;
$domxml->dom_import_simplexml($xml); // load the SimpleXmlElement previously created.
echo $domxml->saveXML();

DomDocument

Or you could do this directly with DOMDocument.

$dom = new DOMDocument('1.0');
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$store = $dom->createElement('store');
$dom->appendChild($store);
$store->appendChild($dom->createElement('date', '2017-09-22 19:30'));
$products = $dom->createElement('products');
$product = $dom->createElement('product');
foreach ($finCombo as $key => $val) {
    $product->appendChild($dom->createElement($key, $val));
}
$products->appendChild($product);
$store->appendChild($products);
echo $dom->saveXML(), PHP_EOL;

XmlWriter

Or, if you want more control (e.g. over indentation), you can use XmlWriter

$writer => new XMLWriter();
$writer->openMemory();
$writer->setIndent(true);
$writer->setIndentString('    ');
$writer->startDocument('1.0', 'UTF-8');
$writer->startElement('store');
$writer->startElement('date');
$writer->text('2017-09-22 19:30');
$writer->fullEndElement(); // end date element
$writer->startElement('products');
$writer->startElement('product');
foreach ($finCombo as $key => $val) {
    $writer->startElement($key);
    $writer->text($val);
    $writer->fullEndElement(); // end $key element
}
$writer->fullEndElement(); // end product element
$writer->fullEndElement(); // end products element
$writer->fullEndElement(); // end store element
$writer->endDocument();
echo $writer->flush(true);

Upvotes: 3

Related Questions