I'm trying to build a 3d php array, that ultimately gets outputted as xml... This is the code I'm trying to use to prove the concept...
$test = array('apple','orange');
$results = Array(
'success' => '1',
'error_number' => '',
'error_message' => '',
'results' => Array (
'number_of_reports' => mysql_num_rows($run),
'item' => $test
)
);
I want the resulting array to look like
<success>1</success>
<error_number/>
<error_message/>
<results>
<number_of_reports>18</number_of_reports>
<item>
<0>apple</0>
<1>orange</1>
</item>
</results>
In reality the apple and orange array would be a 3d one in itself... If you've ever used the ebay api... you'll have an idea of what I'm trying to do (I think)
Try it:
Code:
<?php
$test = array('apple','orange');
$results = Array(
'success' => '1',
'error_number' => '',
'error_message' => '',
'results' => Array (
'number_of_reports' => 1,
'item' => $test
)
);
print_r($results);
function addChild1($xml, $item, $clave)
{
if(is_array($item)){
$tempNode = $xml->addChild($clave,'');
foreach ($item as $a => $b)
{
addChild1($tempNode, $b, $a);
}
} else {
$xml->addChild("$clave", "$item");
}
}
$xml = new SimpleXMLElement('<root/>');
addChild1($xml, $results,'data');
$ret = $xml->asXML();
print $ret;
Output:
<?xml version="1.0"?>
<root><data><success>1</success><error_number></error_number><error_message></error_message><results><number_of_reports>1</number_of_reports><item><0>apple</0><1>orange</1></item></results></data></root>
See below URL. I think it very use full to you:-
How to convert array to SimpleXML
Or Try it:-
$xml = new SimpleXMLElement('<root/>');
array_walk_recursive($test_array, array ($xml, 'addChild'));
print $xml->asXML();
Related
I have a php array and I need to convert it into xml file but I cant get the format I want.
Array:
Array
(
[1] => Array
(
[2000307] => Array
(
[eventid] => 2000307
[eveseq] => 100
[fee] => 200
)
[2000310] => Array
(
[eventid] => 2000310
[eveseq] =>101
[fee] => 300
)
)
)
convert array to xml:
$xml = new SimpleXMLElement('<Event/>');
event_to_xm($array, $xml);
function event_to_xml($array, &$xml) {
$array = json_decode($array,TRUE);
foreach($array as $key => $value) {
foreach($value as $id => $index) {
foreach($index as $title => $result) {
if(is_array($result)) {
if(!is_numeric($title)){
$subnode = $xml->addChild($title);
array_to_xml($result, $xml);
} else {
array_to_xml($result, $xml);
}
} else {
$xml->addChild($title, htmlspecialchars($result));
}
}
}
}
}
event.xml:
<?xml version="1.0"?>
<Event>
<eventid>2000307</eventid>
<eveseq>100</eveseq>
<fee>zz</fee>
<eventid>2000310</eventid>
<eveseq>101</eveseq>
<fee>0</fee>
</Event>
What I expect is that it will create a cd tag when a new array begin:
xml:
<?xml version="1.0"?>
<Event>
<cd>
<eventid>2000307</eventid>
<eveseq>100</eveseq>
<fee>200</fee>
</cd>
<cd>
<eventid>2000310</eventid>
<eveseq>101</eveseq>
<fee>300</fee>
</cd>
</Event>
What I tried:
I tried to direct add a attribute but I encounter this error Call to a member function addChild() on null
$xml=new SimpleXMLElement("event.xml", 0, TRUE);
$child = $xml->event[0]->addChild("cd");
I would take a somewhat different approach - first, use DOMDocument instead of SimpleXML, and, second, use xpath and a fragment to insert elements into the document. Something like this:
$events = array(
"2000307" => array(
"eventid" => 2000307,
"eveseq" => 100,
"fee" => 200,
),
"2000310" => array(
"eventid" => 20003010,
"eveseq" => 101,
"fee" => 300,
)
);
#create a blank document with a root element
$xml = <<<'XML'
<?xml version="1.0"?>
<Event></Event>
XML;
$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMXpath($document);
$expr = "//Event";
#indicate where to insert the new elements
$dest = $xpath->query($expr);
foreach($events as $event) {
$fragment = $document->createDocumentFragment();
#this is the new element to be inserted
$instance = " <cd>
<eventid>{$event['eventid']}</eventid>
<eveseq>{$event['eveseq']}</eveseq>
<fee>{$event['fee']}</fee>
</cd>\n";
$fragment->appendXML($instance);
$dest[0]->appendChild($fragment);
}
$document->formatOutput = TRUE;
echo $document->saveXML();
Output should be your expected output.
You can iterate array data and construct new simplexml object with new 'cd' child. Try like this:
$data = array (
"2000307" => array(
"eventid" => 2000307,
"eveseq" => 100,
"fee" => 200,
),
"2000310" => array(
"eventid" => 20003010,
"eveseq" => 101,
"fee" => 300,
)
);
function to_xml(SimpleXMLElement $object, array $data)
{
foreach ($data as $key => $value) {
if (is_array($value)) {
$new_object = $object->addChild('cd');
to_xml($new_object, $value);
} else {
$object->addChild($key, $value);
}
}
}
$xml = new SimpleXMLElement('<event/>');
to_xml($xml, $data);
print $xml->asXML();
I found a way of doing it and without iterate array data
$xml = new SimpleXMLElement('<Event/>');
event_to_xm($array, $xml);
function event_to_xml($array, &$xml) {
$array = json_decode($array,TRUE);
foreach($array as $key => $value) {
foreach($value as $id => $index) {
if(is_array($value)){
$neweve = $xml->addChild('cd');
}
foreach($index as $title => $result) {
if(is_array($result)) {
$subnode = $xml->addChild($title);
event_to_xml($subnode, $xml);
} else {
$neweve->addChild($title, htmlspecialchars($result));
}
}
}
}
}
i have tryed some things to figure out what wrong with my code, but i dont see the problem.
Simply i have a structured assoziative Array like this:
$data = array(
'field1' => array(
'filed11' => '',
'field12' => array(
'field121' => 'blub'
)
),
'field2' => 'foo',
'field3' => array(
'field31' => 'val',
'field32' => 'other value'
)
);
i have writen a small recursive method to generate an xml from the Array:
protected function buildXmlFromArray(SimpleXMLElement $xml, $data)
{
if(is_array($data)) {
foreach($data as $key => $value) {
if(is_array($value)) {
$child = $xml->addChild($key);
$this->buildXmlFromArray($child, $value);
} else {
$xml->addChild($key, $value);
}
}
}
}
So i generate the root-node and put it in the method:
$xml = new SimpleXMLElement('<root />');
$res = $this->buildXmlFromArray($xml, $data);
print_r($xml->asXML());
exit;
i would expect that iam getting somthing like this:
<?xml version="1.0"?>
<root>
<field1>
<filed11 />
<field12>
<field121>blub</field121>
</field12>
</field1>
<field2>foo</field2>
<field3>
<field31>val</field31>
<field32>other value</field32>
</field3>
</root>
but iam getting an invalid XML:
<?xml version="1.0"?>
<root>
<field1>
<filed11>
<field12>
<field121>blub</field121>
</field12>
</field1>
<field2>foo</field2>
<field3>
<field31>val</field31>
<field32>other value</field32>
</field3>
</root>
so field11 is not closed
Whats wrong with this?
My PHP Version is 7.2.10-0ubuntu0.18.04.1
I'm using the code below to sort the content of my XML file by "WebCategory". My question is how do I save the newly sorted $products array back to the XML file?
<?php
$products = array();
$xml = simplexml_load_file('nwgalaxy-edited.xml');
foreach($xml->Product as $item) {
$products[] = array(
'ProductID' => (string)$item->attributes()->ProductID,
'Description' => (string)$item->Description,
'WebCategory' => (string)$item->WebCategory,
'WebSubCategory' => (string)$item->WebSubCategory,
'WebSubCat2' => (string)$item->WebSubCat2,
'QtyOnHand' => intval($item->QtyOnHand),
'SellingPrice' => intval($item->SellingPrice),
'ListPrice' => intval($item->ListPrice),
'NWGalaxy' => intval($item->NWGalaxy),
'UPC' => intval($item->UPC),
'VendorProductID' => (string)$item->VendorProductID,
'ImageSmall' => (string)$item->ImageSmall,
'ImageLarge' => (string)$item->ImageLarge
);
}
array_sort_by_column($products, 'WebCategory');
function array_sort_by_column(&$array, $column, $direction = SORT_ASC) {
$reference_array = array();
foreach($array as $key => $row) {
$reference_array[$key] = $row[$column];
}
array_multisort($reference_array, $direction, $array);
}
?>
This may work, not tested but should give general idea.
// Create tag products
$xml = new SimpleXMLElement('<products/>');
// Walk the array with callback to method $xml->addChild($this)
array_walk_recursive($products, array($xml, 'addChild'));
// Save generated content to file.
file_put_contents('nwgalaxy-edited.xml', $xml->asXML());
Chaps,
I am trying to get attributes of the 'file' node in the following XML with SimpleXml but every time is gives me back null. I have successfully got the attributes for the study node but fail to get the 'file' atts .
here is the xml :
<?xml version="1.0" encoding="UTF-8"?>
<studies>
<study uid="1.3.12.2" acc="181">
<date>20051218</date>
<time>2156</time>
<ref>CG</ref>
<desc>Abdomen</desc>
<id></id>
<path>S00001</path>
<modality>CR</modality>
<reports>
<file cat="UNK" date="20141124">Card_Cloud.txt</file>
</reports>
</study>
and here is my code :
$studyXML = new SimpleXMLElement($studyXML);
$studyXML_array = array();
foreach ($studyXML ->study as $study)
{
// Getting uid and accession from XML attributes
$uid = (!empty($study)) ? (String)$study->attributes()->uid : '';
$acc = (!empty($study)) ? (String)$study->attributes()->acc : '';
// Getting the reports and putting them in an array
$reports = array ();
foreach($study->reports as $rep)
{
$cat = (String)$rep->attributes()->cat;
$reports[] = (String)$rep->file;
}
// Constructing the xml as an array
$studyXML_array[] = array
(
'uid' => $uid,
'acc' => $acc,
'date' => (String)$study->date,
'reports' => $reports
);
}
I can get "uid" and "acc" but I can't get "cat" and "date" inside file node.
When I look at the array of the xml in my debug variables I can see uid and acc attributes but no sign of cat and date attributes.
I Would really appreciate any help.
I prefer to stick to SimpleXML as all my code is using that so far.
Cheers
This is how I did it based on Ghost answer.
$reports = array ();
foreach($study->reports->file as $rep)
{
$temp = array();
$temp['repName'] = (String)$rep;
// Getting cat and date attributes of the report
foreach($rep->attributes() as $key => $rep)
{
$temp[$key] = (string) $rep;
}
$reports[] = $temp;
}
If you're trying to use print_r()/var_dump() to check, then it will do no justice. But it is there, try to traverse to it along with using ->attributes() inside the foreach as well:
$studyXML = new SimpleXMLElement($studyXML);
$studyXML_array = array();
foreach ($studyXML ->study as $study)
{
// Getting uid and accession from XML attributes
$uid = (!empty($study)) ? (String)$study->attributes()->uid : '';
$acc = (!empty($study)) ? (String)$study->attributes()->acc : '';
// Getting the reports and putting them in an array
$reports = array();
// loop each attribute
foreach($study->reports->file->attributes() as $key => $rep)
{
$reports[$key] = (string) $rep;
}
// Constructing the xml as an array
$studyXML_array[] = array(
'uid' => $uid,
'acc' => $acc,
'date' => (String) $study->date,
'reports' => $reports
);
}
echo '<pre>';
print_r($studyXML_array);
Sample Output:
Array
(
[0] => Array
(
[uid] => 1.3.12.2
[acc] => 181
[date] => 20051218
[reports] => Array
(
[cat] => UNK
[date] => 20141124
)
)
)
In CakePHP I know the XML-class in cake.libs. What I like on this easy to use class is the fact that you can convert an array to xml with attributes.
On a current project I'm working with Zend Framework and I am missing this nice class.
Does anybody know how I can convert an PHP-array to XML with attributes easily?
I tried this one but unfortunately its not easy to handle result arrays from database cause you have to define the attributes inside the array.
Maybe I have missed something in ZF? Or does anybody know how to adapt the CakePHP class to ZF?
Many thanks for any helpful hints.
This function will allow you to create XML document with simple PHP array variable. Nodes are just stacked onto each other and naming it 'Attribute_XXX' will add atribute XXX to that parent node.
function to_xml(SimpleXMLElement $object, array $data)
{
$attr = "Attribute_";
foreach ($data as $key => $value) {
if (is_array($value)) {
$new_object = $object->addChild($key);
to_xml($new_object, $value);
} else {
if(strpos($key, $attr) !== false){
$object->addAttribute(substr($key, strlen($attr)), $value);
}else{
$object->addChild($key, $value);
}
}
}
}
Usage:
$my_array = array (
'TagN1' => array (
'TagInsideOfIt' => array (
'Atrribute_IDuser' => 'anything',
'RegularTag' => 'whatever',
'Address' => array(
'Attribute_ID' => '111',
'Attribute_key' => 'aaa',
'Company' => 'Google Inc.'
)
)
)
);
$xml = new SimpleXMLElement('<root/>');
to_xml($xml, $my_array);
Header('Content-type: text/xml');
print($xml->asXML());
You can get some answers at this URL How to convert array to SimpleXML
An alternative/fast and easy approach would be to convert array data into JSON, that would be faster as well using Zend library. Converting array into JSON is very easy as using follows functions.
Zend_Json::encode() and Zend_Json_Encoder::encode()
Tanks, a using the code of #jezda159 and i modified for me, this is my code:
the array:
$elements_array = array(
"node" => array(
"subnode" => array(
"[attribute]" => "valueOfAttribute",
"[second-attribute]" => "valueOfAttribute",
"second-subnode" => array(
"[attribute]" => "valueOfAttribute",
"[second-attribute]" => "valueOfAttribute",
),
"ListOfElements" => array(
"one",
"two",
"tree"
)
)
),
);
The code:
function array_to_xml($data, $object){
foreach ($data as $key => $value) {
$keyname = is_numeric( $key ) ? "item".$key : $key;
if (is_array($value)) {
$new_object = $object->addChild($keyname);
array_to_xml($value, $new_object);
} else {
preg_match("#\[([a-z0-9-_]+)\]#i", $keyname, $attr);
if( count($attr) ){
$object->addAttribute($attr[1], $value);
}else{
$object->addChild($keyname, $value);
}
}
}
}
$xml_user_info = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8" ?><Elements></Elements>');
//function call to convert array to xml
array_to_xml($elements_array,$xml_user_info);
header('Content-type: text/xml');
//show generated xml file
echo $xml_user_info->asXML();
The result:
<?xml version="1.0" encoding="UTF-8"?>
<Elements>
<node>
<subnode attribute="valueOfAttribute" second-attribute="valueOfAttribute">
<second-subnode attribute="valueOfAttribute" second-attribute="valueOfAttribute"/>
<ListOfElements>
<item0>one</item0>
<item1>two</item1>
<item2>tree</item2>
</ListOfElements>
</subnode>
</node>
</Elements>