CodeIgniter - Process Simple XML & PHP - php

in the controller I have _send method. This method returns something like below:
$xmlstr = <<<XML
<?xml version='1.0' standalone='yes' ?>
<status id="555555555" date="Wed, 28 Mar 2013 12:35:00 +0300">
<id>3806712345671174984921381</id>
<id>3806712345671174984921382</id>
<id>3806712345671174984921383</id>
<id>3806712345671174984921384</id>
<state error="Unknown1">Rejected1</state>
<state error="Unknown2">Rejected2</state>
<state error="">Accepted</state>
<state error="">Accepted</state>
</status>
XML;
This method called:
$req = $this->_send('bulk',$all_phones,$this->input->post('message'));
I am unable to create array or object suitable for passing to model for inserting into DB.
Below what I have now.
$xml = new SimpleXMLElement($xmlstr);
foreach ($xml as $child) {
if ($child->getName() == 'id') {
$id[] = $child->id;
}
if ($child->getName() == 'state') {
$state[] = $child;
//$state[] = $child['error'];
}
}
return array_merge($id,$state);
I am attempting to achieve something like this array:
array(0 => array(
'id' => '3806712345671174984921381',
'state' => 'Rejected1',
'state_error' => 'Unknown1'),
1 => array( ....
Problem with error attribute with fault array_merge.
Any ideas?

You can do write this using a simple while statement.
$cnt=$xml->id->count();$i=0;
while($i<$cnt)
{
$new_arr[$i]['id']=(string)$xml->id[$i];
$new_arr[$i]['state'] = (string)$xml->state[$i];
$new_arr[$i]['state_error'] = (string)$xml->state[$i]['error'];
$i++;
}
print_r($new_arr);
Demonstration

This is how you could do it:
// Load XML
$xmlstr = '<?xml version="1.0" standalone="yes" ?>
<status id="555555555" date="Wed, 28 Mar 2013 12:35:00 +0300">
<id>3806712345671174984921381</id>
<id>3806712345671174984921382</id>
<id>3806712345671174984921383</id>
<id>3806712345671174984921384</id>
<state error="Unknown1">Rejected1</state>
<state error="Unknown2">Rejected2</state>
<state error="">Accepted</state>
<state error="">Accepted</state>
</status>';
$xml = new SimpleXMLElement($xmlstr);
// Init
$parsed_data = array();
// Parse Id
foreach ($xml->id as $id)
{
$parsed_data[] = array(
'id' => (string)$id,
'state' => '',
'state_error' => ''
);
}
// Parse State & State Error
$i = 0;
foreach ($xml->state as $state)
{
$parsed_data[$i]['state'] = (string)$state;
$parsed_data[$i]['state_error'] = (string)$state['error'];
$i++;
}
// Output
var_dump($parsed_data);
Here's the output I got:

Related

how to correctly append xml child elements in php

I'm trying to iterate over an array of movie names and am struggling as shown below. I've included the actual output vs expected output. thanks!
$root = new SimpleXMLElement('<movies/>');
$movies = ['foo', 'bar'];
foreach($movies as $movie_name){
$movie_el = buildMovieTag($movie_name);
$root->addChild($movie_el->asXML());
}
function buildMovieTag($name){
$movie_tag = new SimpleXMLElement('<movie/>');
$movie_tag->addChild('name', $name);
return $movie_tag;
}
I'm expecting this:
<?xml version="1.0"?>
<movies>
<movie><name>foo</name></movie>
<movie><name>bar</name></movie>
</movies>
but am getting this:
<?xml version="1.0"?>
<movies><<?xml version="1.0"?> // extra xml tag
<movie><name>foo</name></movie>
/><<?xml version="1.0"?> // extra xml tag
<movie><name>bar</name></movie>
/></movies>
The new SimpleXMLElement then asXML() is the issue.
addChild is enough to make the element then its return value is the node, then subsequent addChild's on the node make the children.
<?php
$root = new SimpleXMLElement('<movies/>');
$movies = ['foo', 'bar'];
foreach($movies as $movie_name) {
$movie = $root->addChild('movie');
buildMovieTag($movie, $movie_name);
}
function buildMovieTag($node, $name) {
$node->addChild('name', $name);
}
echo $root->saveXML();
<?xml version="1.0"?>
<movies><movie><name>foo</name></movie><movie><name>bar</name></movie></movies>
Edit: if your data is more extensive, structure it so its standard key/value array then loop over the items. The actual issue to the original question is noted on the first line of the answer.
<?php
$root = new SimpleXMLElement('<movies/>');
$movies = [
['name'=>'foo', 'released' => '2020-12-01 00:00:00', 'plot' => 'foo is a foofoo'],
['name'=>'bar', 'released' => '2020-12-02 00:00:00', 'plot' => 'bar is a barbar'],
];
foreach ($movies as $movie) {
buildMovieTag($root->addChild('movie'), $movie);
}
function buildMovieTag($node, $data) {
foreach ($data as $key => $item) {
// just year from datetime string
if ($key === 'released') $item = date_create($item)->format('Y');
$node->addChild($key, $item);
}
}
echo $root->saveXML();
Result (manual formatted)
<?xml version="1.0"?>
<movies>
<movie>
<name>foo</name>
<released>2020</released>
<plot>foo is a foofoo</plot>
</movie>
<movie>
<name>bar</name>
<released>2020</released>
<plot>bar is a barbar</plot>
</movie>
</movies>

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

PHP Create well formatted XML out of SQL result [duplicate]

This question already has answers here:
How to generate XML file dynamically using PHP?
(8 answers)
Closed 3 years ago.
I have a problem. I am struggling for a few days now to create a well formatted XML.
I already created this code, but I have no idea if this is what I need:
$sql = "SELECT * FROM Contacts ORDER BY Id ASC";
$result = $conn->query($sql);
$arr_contacts = array();
while ($row = mysqli_fetch_assoc($result))
{
$contact_array = array(
$row["Id"]=>array(
'id'=>$row["Id"],
'name'=>$row["Name"])
);
$arr_contacts = array_merge($arr_contacts, $contact_array);
}
Now I want a XML like this:
<?xml version="1.0"?>
<Contacts>
<Contact>
<id>1</id>
<name>Smith</name>
</Contact>
<Contact>
<id>2</id>
<name>John</name>
</Contact>
<Contact>
<id>3</id>
<name>Viktor</name>
</Contact>
</Contacts>
The problem is that I don't understand XML very well, so my result is as following:
1Smith2John3Viktor
I used his code: https://www.codexworld.com/convert-array-to-xml-in-php/
How can I get the result I want?
You can use the following example which responds to your need :
$contact_array = array(
array(
'id'=>1,
'name'=>'Ali'),
array(
'id'=>2,
'name'=>'John'),
array(
'id'=>3,
'name'=>'Victor')
);
// Function that converts your array to Xml Object
function toXml(SimpleXMLElement $xml, array $data, $mainKey = null)
{
foreach ($data as $key => $value) {
// if the key is an integer, it needs text with it to actually work.
if (is_numeric($key)) {
$key = $mainKey ? : "key_$key";
}
if (is_array($value)) {
$childXml = $xml->addChild($key);
toXml($childXml, $value);
} else {
$xml->addChild($key, $value);
}
}
return $xml;
}
// Pretty print Xml
function formatXml($simpleXMLElement)
{
$xmlDocument = new DOMDocument('1.0');
$xmlDocument->preserveWhiteSpace = false;
$xmlDocument->formatOutput = true;
$xmlDocument->loadXML($simpleXMLElement->asXML());
return $xmlDocument->saveXML();
}
$xml = toXml(new SimpleXMLElement('<Contacts/>'), $contact_array, 'Contact');
// $output = $xml->asXML();
print formatXml($xml);
// Which prints the following
<?xml version="1.0"?>
<Contacts>
<Contact>
<id>1</id>
<name>Ali</name>
</Contact>
<Contact>
<id>2</id>
<name>Vincent</name>
</Contact>
<Contact>
<id>3</id>
<name>Victor</name>
</Contact>
</Contacts>
You can live test it here: http://sandbox.onlinephpfunctions.com/code/230507b1113504fc37427384e3609d0d0cb95f43
Note, You can ignore the Keys of your elements (so they remain numeric) so it become and use same functions as the example above :
$sql = "SELECT * FROM Contacts ORDER BY Id ASC";
$result = $conn->query($sql);
$arr_contacts = array();
while ($row = mysqli_fetch_assoc($result))
{
$contact_array = array(
array(
'id'=>$row["Id"],
'name'=>$row["Name"])
);
$arr_contacts = array_merge($arr_contacts, $contact_array);
}
Hope It helps !

Find and fill XML nodes from a PHP object

First of all, sorry about my english.
So, I have an XML with a lot of nodes, like:
<first>
<second>
<third/>
<fourth/>
</second>
<fifth>
<sixth>
<seventh/>
</sixth>
</fifth>
</first>
and I have an object, like:
Object{
third: "asd",
fourth: "asdasd",
seventh: "asdasdasd"
}
How can I run through all the nodes of the XML, regardless of their parents, and fill every one of them with the values of the existing properties from the object?
Here's an approach using the SimpleXML:
<?php
$object = (object) array(
'third' => 'asd',
'fourth' => 'asdasd',
'seventh' => 'asdasdasd'
);
$xml = <<<XML
<first>
<second>
<third />
<fourth />
</second>
<fifth>
<sixth>
<seventh />
</sixth>
</fifth>
</first>
XML;
$sxe = new SimpleXMLElement($xml);
foreach ($object as $key => $value) {
$node = $sxe->xpath("//*[./{$key}]");
$node[0]->{$key} = $value;
}
echo $sxe->asXML();
Output:
<?xml version="1.0"?>
<first>
<second>
<third>asd</third>
<fourth>asdasd</fourth>
</second>
<fifth>
<sixth>
<seventh>asdasdasd</seventh>
</sixth>
</fifth>
</first>

inserting an object into an array of objects php

I am trying to write a php script which will insert an object into an array of objects which is originally in XML format. I need to insert the object at a specified index and then be able to re-write the xml file from which the data was pulled with the updated object. Here is the structure of my XML
<?xml version="1.0" encoding="UTF-8"?>
<Bars>
<Bar>
<BarName>Kam's</BarName>
<bar_id>0</bar_id>
<Bartenders>
<Bartender>
<fname>Max</fname>
<lname>Vest</lname>
<imageURL>http://uofi-bars.com/bartenderImages/maxvest.jpg</imageURL>
<shift>2</shift>
</Bartender>
</Bartenders>
<Events>
<Event>
<EventName>Kams event</EventName>
<date>08/10/1989</date>
</Event>
</Events>
<Specials>
<Special>Kam's Special 1</Special>
<Special>Kam's Special 2</Special>
</Specials>
</Bar>
So in other words, if I have a bartender who works at a bar with an id of bar_id = 0, I need to be able to insert that bartender into the array of bartenders for that particular bar.
I use the following php code to create the arrays from XML:
function objectsIntoArray($arrObjData, $arrSkipIndices = array())
{
$arrData = array();
// if input is object, convert into array
if (is_object($arrObjData)) {
$arrObjData = get_object_vars($arrObjData);
}
if (is_array($arrObjData)) {
foreach ($arrObjData as $index => $value) {
if (is_object($value) || is_array($value)) {
$value = objectsIntoArray($value, $arrSkipIndices); // recursive call
}
if (in_array($index, $arrSkipIndices)) {
continue;
}
$arrData[$index] = $value;
}
}
return $arrData;
}
$xmlUrl = "Bars.xml"; // XML
$xmlStr = file_get_contents($xmlUrl);
$xmlObj = simplexml_load_string($xmlStr);
$arrXml = objectsIntoArray($xmlObj);
print_r($arrXml);
I guess I just don't know how to refer to this array of objects within an array of objects... Any help would be greatly appreciated!
Thanks!
if you just replace your code:
$xmlUrl = "Bars.xml"; // XML
$xmlStr = file_get_contents($xmlUrl);
$xmlObj = simplexml_load_string($xmlStr);
$arrXml = objectsIntoArray($xmlObj);
print_r($arrXml);
with this:
$xmlUrl = "Bars.xml"; // XML
$xmlStr = file_get_contents($xmlUrl);
$xml = new SimpleXMLElement($xmlStr);
$bartenders = $xml->xpath('//Bartenders');
$new_bartender = $bartenders[0]->addChild('Bartender');
$new_bartender->fname = 'test1';
$new_bartender->lname = 'test2';
$new_bartender->imgURL = 'http://test.com';
$new_bartender->shift = '0';
print_r($bartenders);
this should do the trick, just replace the values with appropriate values :) i hope this helps!!

Categories