I’ve been working with the Google Contacts API lately and needed to construct some XML as a part of that. PHP’s DOMDocument
works really great for this, but it can get complicated fast as you need to create lots of variables for all of your elements, children, etc. It can make it quite hard to do dynamically.
An easier method would be to just convert an array into XML, the opposite of simplexml_load_string()
if you will. So I wrote some code that does exactly that and I thought I’d share it incase anyone else would find it helpful. 🙂
Start by creating your array of data. I used a numeric array instead of an associative array because you can have duplicate elements in XML while you cannot have duplicate array keys.
$data = array( 'name' => 'toplevelelement', // "name" required, all else optional 'attributes' => array( 'foo' => 'bar', 'fruit' => 'apple', ), 'value' => 'Some random value.', array( 'name' => 'achildelement', 'value'=> 'Value', ), array( 'name' => 'anotherchildelement', 'attributes' => array( 'some' => 'attr', ), array( 'name' => 'grandchildelement', ), ), );
An array such as that is easy to dynamically create based on your source data, it’s easy to read, and can be fairly easily manipulated.
name
is the only required item of each array and it’s the tag name of the element. attributes
is an array of attributes for the element and value
is the value. Both of these are optional. Any children arrays are children elements and their structures should be the same.
Now here’s the code I wrote that converts the above array into some XML:
function generate_xml_element( $dom, $data ) { if ( empty( $data['name'] ) ) return false; // Create the element $element_value = ( ! empty( $data['value'] ) ) ? $data['value'] : null; $element = $dom->createElement( $data['name'], $element_value ); // Add any attributes if ( ! empty( $data['attributes'] ) && is_array( $data['attributes'] ) ) { foreach ( $data['attributes'] as $attribute_key => $attribute_value ) { $element->setAttribute( $attribute_key, $attribute_value ); } } // Any other items in the data array should be child elements foreach ( $data as $data_key => $child_data ) { if ( ! is_numeric( $data_key ) ) continue; $child = generate_xml_element( $dom, $child_data ); if ( $child ) $element->appendChild( $child ); } return $element; } $doc = new DOMDocument(); $child = generate_xml_element( $doc, $data ); if ( $child ) $doc->appendChild( $child ); $doc->formatOutput = true; // Add whitespace to make easier to read XML $xml = $doc->saveXML();
You first create a blank canvas by creating a new instance of the DOMDocument
class and then you pass the class instance (needed for creating elements in the correct character set and such) and the data array to the generate_xml_element()
function. This function will create the top level element and then recursively call itself on any child elements until it’s gone through the whole array.
Once it’s done, you’ll need to append the element to the DOM using the inherited appendChild()
function. Then calling saveXML
will give you the XML output. The above example data array will give you something like this (maybe or maybe not nicely formatted with whitespace depending on what mood DOMDocument
is in):
<?xml version="1.0"?> <toplevelelement foo="bar" fruit="apple"> Some random value. <achildelement>Value</achildelement> <anotherchildelement some="attr"> <grandchildelement></grandchildelement> </anotherchildelement> </toplevelelement>
And there you have it!
I tried your creating an XML file from a PHP array. I used your example and could not the XML tree, only the values. I am probably missing something. I have been using PHP for over a dozen years, however this is the first time I tried to turn a PHP array in an XML output. If I ask real nice you assist me?
I would like to take this sample array and turn it into a similar XML out as the example below.
With XML, I believe you need to have a single top level element to contain all of your data. Even if you don’t, my code requires one, so I made it “location”.
Now the dumb question of the day; How do I get it to display as an XML tree like yours? I feel like such a novice today.
Mine comes out as one long of only the values;
95610Citrus HeightsKMCCMcClellan Airfield7.306701182156538.667-121.4
If you’re
echo
‘ing it, then your browser is probably trying to render it as HTML tags. Usevar_dump()
or view the source.Thank you for everything. “View Source” does not seem to work. The var_dump($xml) does not give me that XML format.
Result from var_dump($xml:
string(223) ” 95610Citrus HeightsKMCCMcClellan Airfield7.306701182156538.667-121.4 “
If you wrap the output in htmlentities() you’ll get the response as XML.
add header( “content-type: application/xml; charset=ISO-8859-15” ); in your code
Hi, I need your help.
xml file:
——————————————–
This way you can print:
STOKLAR->STOK as $stok) {
foreach ($stok->OZELLIKLER as $ozellikler) {
for ($i=0;$i <=count($ozellikler);$i++){
echo '’ ;
echo ” ;
echo ”.$ozellikler->OZELLIK[$i].”;
echo ‘:’;
echo ”.$ozellikler->DEGER[$i].”;
echo ” ;
echo ” ;
$i++;
}
}
}
?>
—————————————————-
However, only the html table is added to the database, data is not added into HTML table cells.
$xmlData = simplexml_load_file($xml_directory.$this->code.”/exaproperties.ashx”);
foreach ($xmlData->STOKLAR->children() as $STOK) {
foreach ($STOK->children() as $OZELLIKLER => $data) {
for ($i=0;$i <=count($data);$i++){
$tablo = '';
$tablo.= '’ ;
$tablo.= ” ;
$tablo = ”.$data->OZELLIK[$i].”;
$tablo.= ‘::’;
$tablo.= ”.$data->DEGER[$i].”;
$tablo.= ” ;
$tablo.= ” ;
}
}
}
—————————————-
If the support I rejoice.(Sorry for bad english)
How do i generate a tree structure like a parent can have a child and that child can be a parent to another child
Just keep nesting your arrays.
Great post! I am trying build a xml file that i can turn into a visio file for later. Have you had any experience with that?
Nope, sorry.
can you give the link where can we download the whole codes?
The whole code is right in the post. It’s just a simple function call that you pass a structured array to.
I have this in one php file
‘toplevelelement’, // “name” required, all else optional
‘attributes’ => array(
‘foo’ => ‘bar’,
‘fruit’ => ‘apple’,
),
‘value’ => ‘Some random value.’,
array(
‘name’ => ‘achildelement’,
‘value’=> ‘Value’,
),
array(
‘name’ => ‘anotherchildelement’,
‘attributes’ => array(
‘some’ => ‘attr’,
),
array(
‘name’ => ‘grandchildelement’,
),
),
);
function generate_xml_element( $dom, $data ) {
if ( empty( $data[‘name’] ) )
return false;
// Create the element
$element_value = ( ! empty( $data[‘value’] ) ) ? $data[‘value’] : null;
$element = $dom->createElement( $data[‘name’], $element_value );
// Add any attributes
if ( ! empty( $data[‘attributes’] ) && is_array( $data[‘attributes’] ) ) {
foreach ( $data[‘attributes’] as $attribute_key => $attribute_value ) {
$element->setAttribute( $attribute_key, $attribute_value );
}
}
// Any other items in the data array should be child elements
foreach ( $data as $data_key => $child_data ) {
if ( ! is_numeric( $data_key ) )
continue;
$child = generate_xml_element( $dom, $child_data );
if ( $child )
$element->appendChild( $child );
}
return $element;
}
$doc = new DOMDocument();
$child = generate_xml_element( $doc, $data );
if ( $child )
$doc->appendChild( $child );
$doc->formatOutput = true; // Add whitespace to make easier to read XML
$xml = $doc->saveXML();
?>
But I get white blank page only
Sounds like you have a PHP error. Check your error_log and/or turn on display_errors to see what the error is.
There’s no error in the error_log
That ist awesome. This is the first lib I found that also works for my case. Thank you 🙂
hi this post is obviously old but hope u can help me tweak your code a little – i need a further nested array to be allowed, but in your code, it exits if there is no ‘name’ tag at the next level.
I need to allow the inner DEPENDENT array in this example:
[2] => Array
(
[name] => Status
[attributes] => Array
(
[Status] => Married
)
)
[3] => Array
(
[0] => Array
(
[name] => Dependent
[attributes] => Array
(
[Age] => 7
)
)
[1] => Array
(
[name] => Dependent
[attributes] => Array
(
[Age] => 3
)
)
)
Hope that makes sense and u can still help 🙂
Can this support CDATA?
Great compact piece of code, works out of the box. Thank you very much for saving hours of experimenting!