0

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

  • Possible duplicate of [How to generate XML file dynamically using PHP?](https://stackoverflow.com/questions/486757/how-to-generate-xml-file-dynamically-using-php) – Jeff Oct 16 '17 at 09:51
  • 1
    Ok, it seems that your problem is not creating an XML file, but rather that you get multiple values in your array. Please post your code, so we can see what your error is. Also, don't ask two questions in the same question. Create a new question for your second part. – Xyz Oct 16 '17 at 10:18
  • Checkout your `$color` variable. It is an array not a string. – SaidbakR Oct 16 '17 at 11:17
  • 1
    Checkout your `$color` variable. It is an array not a string. In other words to get an XML like descriped you should have an array of products its elements are associative array for each product and that associative array should not has arrays as values. i.e `[0 => ['SKU' => '10206 red', 'productID' => '288-red','size' => 'small, large'],1=>[],...` – SaidbakR Oct 16 '17 at 11:23

1 Answers1

3

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);
Xyz
  • 5,955
  • 5
  • 40
  • 58
  • 1
    Rather than converting to a string and back with `$domxml->loadXML($xml->asXML());`, you should use [`dom_import_simplexml`](http://php.net/dom_import_simplexml) which directly re-wraps the object in memory (the two APIs work on the same underlying structures). I've checked, and this still lets you set the pretty-print flags on the document: https://3v4l.org/WtPsI – IMSoP Oct 16 '17 at 10:23
  • Great comment, I will update the answer in a moment. – Xyz Oct 16 '17 at 10:30
  • okay, so here's what we get with the DOMDocument solution: `Warning: DOMDocument::createElement() expects parameter 2 to be string, array given in C:\xampp\htdocs\get_content\index.php on line 203 Fatal error: Uncaught TypeError: Argument 1 passed to DOMNode::appendChild() must be an instance of DOMNode, null given in C:\xampp\htdocs\get_content\index.php:203 Stack trace: #0 C:\xampp\htdocs\get_content\index.php(203): DOMNode->appendChild(NULL) #1 {main} thrown in C:\xampp\htdocs\get_content\index.php on line 203` – Miloš Miljković Oct 16 '17 at 10:43
  • here is what print_r shows for the array that I need to convert to xml (this is the first entry): `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 )))` – Miloš Miljković Oct 16 '17 at 10:53
  • 1
    @MilošMiljković, I see your problem now. Your array is an array of arrays. This is probably due to your use of `array_push()`, which pushes the variable/object you are passing it onto the array you specify. If you try to push an array onto another array, you will simply get an array containing an array. What I guess you want to do is use array_merge (http://php.net/array_merge) – Xyz Oct 16 '17 at 11:17
  • @MilošMiljković, I updated my answer with code examples on array_merge vs array_push (plus a bonus section on XmlWriter). Please give it a shot and let us know if it works for you. – Xyz Oct 16 '17 at 11:37
  • This works great, actually the part with the array merging is not necessary because there is an iteration going on for each product and it stores each products info in array so I do the pushing to escape the loop, anyway, what should I do about the other question? I need to loop through the array to find all the products with the same "productID" and merge their "size" in array. – Miloš Miljković Oct 16 '17 at 12:14
  • @AronCederholm I have posted another question regarding the array issue. You may find it in the link below: https://stackoverflow.com/questions/46775864/find-all-items-with-the-same-key-in-array-and-combine-them-in-a-new-one – Miloš Miljković Oct 16 '17 at 17:29