how to pass XML setAttribute in php foreach - php

I want to generate XML for an array which has many field and i want to set that fields in a single XML element as attributes of that element below is my php code.
<?php
$rs=array();//values come in $rs from database, it has many fields
$doc = new DOMDocument();
$doc->formatOutput = true;
$root = $doc->createElement( "slides" );
$doc->appendChild( $root );
$firstchild = $doc->createElement( "device" );
$fs=$doc->appendChild( $firstchild );
foreach( $rs as $key=>$value ){
$fs->setAttribute($key,$value);
}
$xml_string = $doc->saveXML();
echo $xml_string;
But this is not working for me, it gives me an error like:
DOMElement:setAttribute() expects parameter 2 to be string,array given
My $rs array structure is like:
Array
(
[0] => Array
(
[id] => 1
[name] => dfd
[width] => 2
[height] => 1
[resolution] =>
[space] =>
)
)
, i want output like:
<slides>
<device id="12" name="mydevice" color="red" .....and so on></device>
</slides>

You did some mistakes, the main of them that you appendchild element to Document but not to parent
$doc = new DOMDocument();
$doc->formatOutput = true;
$root = $doc->createElement( "slides" );
$doc->appendChild( $root );
$fs = $doc->createElement( "device" );
$root->appendChild( $fs );
foreach( $rs as $key=>$value ){
$fs->setAttribute($key,$value);
}
$xml_string = $doc->saveXML();
echo $xml_string;
working example

You need to create each attribute and assign it to the correct node, something like this:
foreach( $rs as $key => $value ){
$attrib=$doc->createAttribute($key);
$attrib->nodeValue=$value;
$fs->appendChild( $attrib );
}

The $rs variable is an array of the records with an array of the fields as an element. So you need two nested loops.
The outer loop iterates the records and creates an device element node for each record. The inner loop iterates the fields and adds the attributes.
$rs = [
[
'id' => 1,
'name' => 'dfd',
'width' => 2,
'height' => 1,
'resolution' => '',
'space' => ''
]
];
$document = new DOMDocument();
$slides = $document->appendChild(
$document->createElement("slides")
);
foreach ($rs as $record) {
$device = $slides->appendChild(
$document->createElement("device")
);
foreach($record as $key => $value){
$device->setAttribute($key,$value);
}
}
$document->formatOutput = true;
echo $document->saveXML();
Output:
<?xml version="1.0"?>
<slides>
<device id="1" name="dfd" width="2" height="1" resolution="" space=""/>
</slides>

Related

adding node in xml file via php

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

XMl parsing query in php

I'm parsing xml nodes and I'm doing something wrong but I don't know what.
I have this xml:
$xml=" <root>
<info>
<company/>
<user_id>43</user_id>
<currency>EUR</currency>
</info>
<products>
<product>
<id>1336</id>
<pn>NX.RZNAA.003</pn>
<stock>1.00</stock>
</product>
<product>
<id>1337</id>
<pn>NX.RZNAA.004</pn>
<stock>4.00</stock>
<item_number>5</item_number>
</product>
</products>
</root>";
As you can see I have two "product" nodes with child nodes. But in first node "product" I have one node less then in second. In second the node "item_number" is added (it's optional node, if it has value it is in xml otherwise not) . When I'm parsing this nodes my parser returns value from second nodes "product" even if I'm on first node.
Anyone know what is the problem here?
Here is my code:
$xmlDoc = new DOMDocument();
$xmlDoc->load($xml) ;
$xpath = new DOMXPath($xmlDoc);
$tagForCount="count(//".$arrayPolja[0].")";
$x=$xmlDoc->getElementsByTagName("product");
$xpath = new DomXpath($xmlDoc);
$count = 3;
$arrayPolja[0] = "id";
$arrayPolja[1] = "pn";
$arrayPolja[2] = "stock";
$arrayPolja[3] = "item_number";
$r=0;
foreach ($x as $product) {
$i=0;
while ($i<=$count)
{
$polje=$arrayPolja[$i];
$values[$i]=$xpath->query($polje, $product)->item($r)->textContent;
$i++;
}
$r++;
}
For one, the second iteration in the loop is overriding the values of your array "$values" which is why you'd only be seeing the values from the second product node (if you are inspecting the "$values" array which is what I'm assuming you are doing).
Try this:
$xmlDoc = new DOMDocument();
$xmlDoc->load($xml);
$xpath = new DOMXPath($xmlDoc);
$x = $xmlDoc->getElementsByTagName("product");
$array = array('id','pn','stock','item_number');
$values = array();
foreach ($x as $product) {
$data = array();
// node name here
$data['node'] = $product->nodeName;
foreach ($array as $v){
$obj = $xpath->query($v, $product)->item(0);
if (gettype($obj) == 'object'){
$data[$v] = $obj->textContent;
}
}
$values[] = $data;
}
echo '<pre>' . print_r($values, true). '</pre>';
That should produce this:
Array
(
[0] => Array
(
[node] => product
[id] => 1336
[pn] => NX.RZNAA.003
[stock] => 1.00
)
[1] => Array
(
[node] => product
[id] => 1337
[pn] => NX.RZNAA.004
[stock] => 4.00
[item_number] => 5
)

Where is null coming from in this array?

I am converting a php array into xml with something like this :
$bigArray = $readConnection->fetchAll($query);
$doc = new DOMDocument();
$doc->formatOutput = true;
$r = $doc->createElement( "DATA" );
$doc->appendChild( $r );
foreach( $bigArray as $product )
{
$b = $doc->createElement( "ITEM" );
$product_type = $doc->createElement( "PRODUCT_TYPE" );
$product_type->appendChild(
$doc->createTextNode( $product['ProductType'] )
);
$b->appendChild( $product_type );
$sku = $doc->createElement( "SKU" );
$sku->appendChild(
$doc->createTextNode( $product['SKU'] )
);
$b->appendChild( $sku );
$r->appendChild( $b );
}
echo $doc->saveXML();
This returns an xml doc however at the very end null is being appended and I think that is what is causing me other problems. So for example at the bottom of the xml that is output it looks like :
</ITEM>
</DATA>
null
This null value is coming from the original array I see if I do:
print_r($bigArray)
I see something like :
Array ( [0] => Array ( [ProductType] => simple [SKU] => 09423100010018 ) [1] => Array ( [ProductType] => simple [SKU] => 14552300010002 )) null
I am calling this from a class in magento like :
class Foo_Model_Queryone extends Mage_Core_Model_Abstract
{
public function pprQuery() {
$resource = Mage::getSingleton('core/resource');
$readConnection = $resource->getConnection('core_read');
$query = ("SELECT cpe.type_id AS 'ProductType',
cpe.sku AS 'SKU',
.....
The Class Mage_Core_Model_Abstract is causing the problem, or another class higher up, that is outputting the null value.
Try to step through it using Xdebug in Netbeans, and see what is causing the null value. I am interested to see the outcome.
HTH

How to append xml data to xml file without overwriting existing data using php?

HI Guys, Im kinda new to php and xml so pls bear with me.
I wanna how am I gonna append an xml data to an xml file without overwriting the existing data uisng PHP.
I have here the codes:
writexml.php
<?php
$employees = array();
$employees [] = array(
'name' => 'Tom',
'age' => '34',
'salary' => "$10000"
);
$employees [] = array(
'name' => 'Ryan',
'age' => '20',
'salary' => "$2000"
);
$employees [] = array(
'name' => 'Dave',
'age' => '20',
'salary' => "$2000"
);
$doc = new DOMDocument();
$doc->formatOutput = true;
$r = $doc->createElement( "employees" );
$doc->appendChild( $r );
foreach( $employees as $employee )
{
$b = $doc->createElement( "employee" );
$name = $doc->createElement( "name" );
$name->appendChild(
$doc->createTextNode( $employee['name'] )
);
$b->appendChild( $name );
$age = $doc->createElement( "age" );
$age->appendChild(
$doc->createTextNode( $employee['age'] )
);
$b->appendChild( $age );
$salary = $doc->createElement( "salary" );
$salary->appendChild(
$doc->createTextNode( $employee['salary'] )
);
$b->appendChild( $salary );
$r->appendChild( $b );
}
echo $doc->saveXML();
$doc->save("employees.xml")
?>
What happens when I run this code it removes all previous data. Pls help.
You will need to open the existing document to append information to it, your last save will simply overwrite the existing file.
$doc = new DomDocument();
$doc->loadXML(file_get_contents('employees.xml'));
foreach($doc->getElementsByTagName('employees') as $node)
{
// your current xml logic here
}
Update for hafedh
$doc = new DomDocument();
$doc->formatOutput = true;
if($xml = file_get_contents('employees.xml'))
$doc->loadXML($xml);
$nodelist = $doc->getElementsByTagName('employees');
if($nodelist->length === 0)
{
$nodelist = $doc->createElement("employees");
$doc->appendChild($nodelist);
$nodelist = $doc->getElementsByTagName('employees');
}
foreach($nodelist as $key => $node)
{
// Employee Container
$element = $doc->createElement("employee");
$employee = $node->appendChild($element);
// Name Element
$element = $doc->createElement("name");
$name = $employee->appendChild($element);
$element = $doc->createTextNode('CCC');
$name->appendChild($element);
// Age Element
$element = $doc->createElement("age");
$age = $employee->appendChild($element);
$element = $doc->createTextNode('333');
$age->appendChild($element);
}
echo '<pre>' . htmlentities($doc->saveXML());
xml file contents
<employees><employee><name>AAA</name><age>111</age></employee><employee><name>BBB</name><age>222</age></employee></employees>

appending xml data in between nodes using php

$employees = array();
$employees [] = array(
'name' => 'Albert',
'age' => '34',
'salary' => "$1000000000"
);
$employees [] = array(
'name' => 'Claud',
'age' => '20',
'salary' => "$200000000"
);
$doc = new DOMDocument();
$doc->load('xml/text.xml');
$doc->formatOutput = true;
$r = $doc->createElement( "employees" );
$doc->appendChild( $r );
foreach( $employees as $employee )
{
$b = $doc->createElement( "employee" );
$name = $doc->createElement( "name" );
$name->appendChild(
$doc->createTextNode( $employee['name'] )
);
$b->appendChild( $name );
$age = $doc->createElement( "age" );
$age->appendChild(
$doc->createTextNode( $employee['age'] )
);
$b->appendChild( $age );
$salary = $doc->createElement( "salary" );
$salary->appendChild(
$doc->createTextNode( $employee['salary'] )
);
$b->appendChild( $salary );
$r->appendChild( $b );
}
$doc->save("xml/text.xml")
this existing code load and writes data to an xml file, however right now it keeps creating the parent node "employees" over and over again. How would I just append the child nodes to the already existing employees node in the xml file?
Assuming your root node isn't employees, and that there is just one employees node, replace these lines:
$r = $doc->createElement('employees');
$doc->appendChild( $r );
With these:
$tags = $doc->getElementsByTagName('employees');
if ($tags->length) {
$r = $tags->item(0);
} else {
$r = $doc->createElement('employees');
$doc->appendChild( $r );
}
This code uses the first employees node found in the document. If none is found, it appends one to the end of the document. Actually, I'm guessing you want to insert the employees node somewhere inside the document, instead of at the end....
Assuming you already have an XML structure in xml/text.xml with a root node of 'employees' you want to replace this line:
$r = $doc->createElement( 'employees' );
with this line:
$r = $doc->documentElement;

Categories