Creating multiLevel XML document.

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
Noodleyman
Forum Newbie
Posts: 23
Joined: Thu Jun 23, 2011 4:49 pm

Creating multiLevel XML document.

Post by Noodleyman »

Hi Guys,

I have probably overlooked something very simple here, but I can't find any examples in PHP of this working. I need to create a multi Level XML document, in the following format

Example:

Code: Select all

<root>
	<Section1>
		<Item>
			<data1>A VALUE</data1>
			<data2>A VALUE</data2>
			<data3>A VALUE</data3>
		</item>
		<Item>
			<data1>A VALUE</data1>
			<data2>A VALUE</data2>
			<data3>A VALUE</data3>
		</item>
		<Item>
			<data1>A VALUE</data1>
			<data2>A VALUE</data2>
			<data3>A VALUE</data3>
		</item>
	</Section1>
	<Section2>
		<OtherData>
			<data1>A VALUE</data1>
			<data2>A VALUE</data2>
			<data3>A VALUE</data3>
		</OtherData>
		<OtherData>
			<data1>A VALUE</data1>
			<data2>A VALUE</data2>
			<data3>A VALUE</data3>
		</OtherData>
		<OtherData>
			<data1>A VALUE</data1>
			<data2>A VALUE</data2>
			<data3>A VALUE</data3>
		</OtherData>
	</section2>		
</root>
I am already creating simple XML documents, which are a single level.
Example:

Code: Select all

<root>
	<Item>
		<data1>A VALUE</data1>
		<data2>A VALUE</data2>
		<data3>A VALUE</data3>
	</item>
</root>
Can anybody help me out with the method to create multilevel XML?

Thanks :)

Noodle
User avatar
McInfo
DevNet Resident
Posts: 1532
Joined: Wed Apr 01, 2009 1:31 pm

Re: Creating multiLevel XML document.

Post by McInfo »

The most straightforward way to do it would be to open your text editor and type the XML into a new document; but I'm sure you are looking for something a little more dynamic; so you will have to explain the situation in more detail. Where does the data come from? What classes/functions are you using?
Noodleyman
Forum Newbie
Posts: 23
Joined: Thu Jun 23, 2011 4:49 pm

Re: Creating multiLevel XML document.

Post by Noodleyman »

McInfo wrote:The most straightforward way to do it would be to open your text editor and type the XML into a new document; but I'm sure you are looking for something a little more dynamic; so you will have to explain the situation in more detail. Where does the data come from? What classes/functions are you using?
Sure thing. I am using the PHP DOM objects rather than simple_xml.

The XML file is built on a customer server, grabbing selected data from their database. The file is then transfered to a new system, and gets imported.

Alas, manually building the file is not an option, this is for a data transfer between servers. The only thing that will change each time is the SELECT query, thus returning different data. The file can be large and hold a lot of data. I am currently testing with approx 20,000 records which get built into the XML file, but can be anywhere up to 700,000 records when in production.

Here is a sample, which works fine at the moment, providing me with a valid, working XML structure.

<root>
<item>
<field1> DATA FROM FIELD 1</field1>
<field2>DATA FROM FIELD 2</field2>
</item>
<item>
<field1> DATA FROM FIELD 1</field1>
<field2>DATA FROM FIELD 2</field2>
</item>
</root>

Code: Select all

$sql = "SELECT field1 AS FIELD1, field2 AS FIELD2 FROM table";
$query = mysql_query($sql)
 or die(mysql_error());


// create a new XML document
$doc = new DomDocument('1.0', 'UTF-8');

// create root node
$root = $doc->createElement('ebaytools');
$root = $doc->appendChild($root);

// process one row at a time
while($row = mysql_fetch_assoc($query)) {
	// add node for each row
	$occ = $doc->createElement('Item');
	$occ = $root->appendChild($occ);

	// add a child node for each field
	foreach ($row as $fieldname => $fieldvalue) {	
		$child = $doc->createElement($fieldname);
		$child = $occ->appendChild($child);	

		$value = $doc->createTextNode($fieldvalue);
		$value = $child->appendChild($value);		
	}
}

// get completed xml document
$xml_string = $doc->saveXML();
 
// show me what you built
echo $xml_string;
Now, I want to modify the XML structure, allowing me to capture a second set of data from a new query into the same XML file.

This is what I want to get to:

<ebaytools>
<inventory>
<item>
<name>Sausage</name>
<price>3</price>
</item>
<item>
<name>Sausage</name>
<price>3</price>
</item>
</inventory>
<cats>
<category>
<name>one</name>
<id>2</id>
</category>
<category>
<name>two</name>
<id>4</id>
</category>
</cats>
</ebaytools>

Is this possible? I can't get it to work at all.

Thanks in advance,
Noodleyman
Forum Newbie
Posts: 23
Joined: Thu Jun 23, 2011 4:49 pm

Re: Creating multiLevel XML document.

Post by Noodleyman »

update on this..

I am starting to think there is a bug, or this isn't possible in PHP with DOM.

Example:

Code: Select all

<?php

// create a new XML document
$doc = new DomDocument('1.0');

// create root node
$root = $doc->createElement('root');
$root = $doc->appendChild($root);

$occ = $doc->createElement('Item');
$occ = $root->appendChild($occ);

echo htmlentities($doc->saveXML());

?>
This generates the following output:
<?xml version="1.0"?> <root><Item/></root>

Well, clearly that isn't going to work. When creating an empty node. It should be <?xml version="1.0"?> <root><Item></item></root>. With it being self terminating, you can't go multilevel...

If I then add a second node, watch what happens.

Code: Select all

<?php

// create a new XML document
$doc = new DomDocument('1.0');

// create root node
$root = $doc->createElement('root');
$root = $doc->appendChild($root);

$occ = $doc->createElement('Items');
$occ = $root->appendChild($occ);

	$occ = $doc->createElement('Item');
	$occ = $root->appendChild($occ);
	
		$child = $doc->createElement('Name');
		$child = $occ->appendChild($child);
		
		$value = $doc->createTextNode('Noodle');
		$value = $child->appendChild($value);		

		$child = $doc->createElement('Age');
		$child = $occ->appendChild($child);
		
		$value = $doc->createTextNode('12');
		$value = $child->appendChild($value);				
		
echo htmlentities($doc->saveXML());

?>
Outout:
<?xml version="1.0"?> <root><Items/><Item><Name>Noodle</Name><Age>12</Age></Item></root>

Desired Output:
<?xml version="1.0"?> <root><Items><Item><Name>Noodle</Name><Age>12</Age></Item></items></root>

So, instead of giving me an extra child level, it adds a self terminating node, which is not what I want at all!

I haven't found a way around this.

Anybody got any ideas?
User avatar
McInfo
DevNet Resident
Posts: 1532
Joined: Wed Apr 01, 2009 1:31 pm

Re: Creating multiLevel XML document.

Post by McInfo »

Just be careful with your variables.

Code: Select all

<?php
header('Content-Type: text/xml');

$doc = new DOMDocument('1.0');
$doc->formatOutput = true;

$root = $doc->appendChild($doc->createElement('root'));
$items = $root->appendChild($doc->createElement('items'));

$item = $doc->createElement('item');
$item->appendChild($doc->createElement('name', 'Noodle'));
$item->appendChild($doc->createElement('age', '12'));
$items->appendChild($item);

$item = $doc->createElement('item');
$item->appendChild($doc->createElement('name', 'Sausage'));
$item->appendChild($doc->createElement('age', '3'));
$items->appendChild($item);

echo $doc->saveXML();

Code: Select all

<?xml version="1.0"?>
<root>
  <items>
    <item>
      <name>Noodle</name>
      <age>12</age>
    </item>
    <item>
      <name>Sausage</name>
      <age>3</age>
    </item>
  </items>
</root>
This tag style is normal for elements that have no content:

Code: Select all

<empty/>
Noodleyman
Forum Newbie
Posts: 23
Joined: Thu Jun 23, 2011 4:49 pm

Re: Creating multiLevel XML document.

Post by Noodleyman »

McInfo wrote:Just be careful with your variables.

Code: Select all

<?php
header('Content-Type: text/xml');

$doc = new DOMDocument('1.0');
$doc->formatOutput = true;

$root = $doc->appendChild($doc->createElement('root'));
$items = $root->appendChild($doc->createElement('items'));

$item = $doc->createElement('item');
$item->appendChild($doc->createElement('name', 'Noodle'));
$item->appendChild($doc->createElement('age', '12'));
$items->appendChild($item);

$item = $doc->createElement('item');
$item->appendChild($doc->createElement('name', 'Sausage'));
$item->appendChild($doc->createElement('age', '3'));
$items->appendChild($item);

echo $doc->saveXML();

Code: Select all

<?xml version="1.0"?>
<root>
  <items>
    <item>
      <name>Noodle</name>
      <age>12</age>
    </item>
    <item>
      <name>Sausage</name>
      <age>3</age>
    </item>
  </items>
</root>
This tag style is normal for elements that have no content:

Code: Select all

<empty/>

Clearly, I have been an idiot :)

Thank you sir! you've made my day
Post Reply