appending xml data in between nodes using php - 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;

Related

how to pass XML setAttribute in php foreach

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>

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>

Dynamic formation of variable name in PHP?

The code below dynamically concatenates keys to an existing array $options_pool. So the final form should be: $options_pool[ $base_key ][ $first_key ][ $second_key ]... This is so I can dynamically assign a value to the elements of the array $options_pool which is multidimensional.
foreach( $this->post_vars as $name => $value ) {
//Look for $name key in array $options_pool if it exists.
//Use multi_array_key_exists() to handle the task
//It should return something like "fruit:mango:apple_mango"
//Then dynamically call $options_pool based on the data. Like so: $options_pool[ 'fruit' ][ 'mango' ][ 'apple_mango' ] = $value;
$match_key = multi_array_key_exists( $name, $options_pool );
$option_keys = explode( ':', $match_key );
$option_keys_length = count( $option_keys );
$option_name_array = array();
if( 0 < $option_keys_length ) {
for( $c = $option_keys_length; $c > 0; $c-- ) {
$sub_keys = '$options_pool';
for( $c_sub = 0; $c_sub < $c ; $c_sub++ ) {
$sub_keys .= '[ $option_keys[ '. $c_sub . ' ] ]';
}
$option_name_array[] = $sub_keys;
}
foreach( $option_name_array as $f_var_name ) {
//the following line should equal to: $options_pool[ 'fruit' ][ 'mango' ][ 'apple_mango' ] = $value;
$f_var_name = $value;
}
}
}
//The $options_pool array
$options_pool = array( 'car' => '', 'animals' => '', 'fruit' => array( 'mango' => array( 'apple_mango' => '' ));
I think the logic is correct except that this portion of the code:
foreach( $option_name_array as $f_var_name ) {
$f_var_name = $value; //particularly this line
}
doesn't work? I've tested printing the value of $f_var_name and the result is correct but it doesn't really call the array?
That is incorrect, you are right.
The variable name will always be $options_pool.
You can pass the keys as explode(':', $name) and later assign them.
By the way, your code at
foreach( $option_keys as $option_keys_value ) {
$option_key_names[] = $option_keys_value;
}
Do you realize that it just copies $option_keys as $option_key_names just as if you had written $option_key_names = $option_keys; (in this code) ?
Maybe with a stack you could do this iteratively but with recursion it is just more natural, as you see here
function getVariableToWrite(&$reference, $nested_opts, $write) {
if(empty($nested_ops)) // Base case
return $reference = write;
if(isset($reference[array_shift($nested_ops)]))
return getVariableToWrite($reference, $nested_ops, $write);
throw new Exception("The key does not exist..");
}
And then just
foreach( $this->post_vars as $name => $value ) {
// Your work over here until...
$match_key = "fruit:mango:apple_mango";
$option_keys = explode( ':', $match_key );
getVariableToWrite($options_pool, $option_keys, $value);
}
Will this do the work?
In your foreach, you need to pass the value by reference, so you can edit it.
foreach( $option_name_array as &$f_var_name ){
$f_var_name = $value;
}
Try this...
foreach( $option_name_array as $key => $f_var_name ) {
$option_name_array[$key] = $value; //particularly this line
}

rss parsing DOMDocument in PHP

I'm trying to get all categories and push them into my array, so far I'm doing it this way:
$doc = new DOMDocument();
$doc->load('myxml.xml');
$arr = array();
foreach ($doc->getElementsByTagName('item') as $node) {
$items = array (
'title' => $node->getElementsByTagName('title')->item(0)->nodeValue,
'date' => $node->getElementsByTagName('category')->item(0)->nodeValue
);
$arr [] = $items ;
}
This works if we have only 1 cat, however, my xml has several categories per item. What would be a good way of doing this?
<item>
<title>Submit</title>
<category>Foo</category>
<category>Bar</category>
</item>
Thanks
This should help:
$doc = new DOMDocument();
$doc->load('myxml.xml');
$arr = array();
foreach ($doc->getElementsByTagName('item') as $node) {
$item = array (
'title' => $node->getElementsByTagName('title')->item(0)->nodeValue,
'date' => array()
);
foreach($node->getElementsByTagName('category') as $catNode)
{
$item['date'][] = $catNode->nodeValue;
}
$arr[] = $item;
}
Christian
You need nested loops:
$doc = new DOMDocument();
$doc->load('myxml.xml');
$arr = array();
foreach ($doc->getElementsByTagName('item') as $itemNode) {
$items = array(
'title' => $itemNode->getElementsByTagName('title')->item(0)->nodeValue,
'date' => array()
);
foreach ($itemNode->getElementsByTagName('category') as $categoryNode) {
$items['date'][] = $categoryNode->nodeValue;
}
$arr[] = $items;
}

Categories