I do not understand these node value things at all i am trying to replicate an xml design in php but having quite a bit of trouble the file i am trying to reproduce through php is.
<items>
<item>
<id></id>
<name></name>
<price></price>
<quantity></quantity>
<description></description>
<qonhold></qonhold>
<qsold></qsold>
</item>
</items>
And the PHP file to recreate this is almost all done
$dom = new DOMDocument("1.0");
// create root element
$root = $dom->createElement("Items");
$dom->appendChild($root);
$dom->formatOutput=true;
// create child element
$item = $dom->createElement("item");
$dom->appendChild($item);
// create text node
$id = $dom->createElement("id");
$root->appendChild($id);
$name = $dom->createElement("name");
$root->appendChild($name);
$price = $dom->createElement("price");
$root->appendChild($price);
$quantity = $dom->createElement("quantity");
$root->appendChild($quantity);
$description = $dom->createElement("description");
$root->appendChild($description);
$qonhold = $dom->createElement("qonhold");
$root->appendChild($qonhold);
$qsold = $dom->createElement("qsold");
$root->appendChild($qsold);
The problem i am having is its saving it all under "items" being the root.. but i can not get everything id, name, price, quantity, description, qonhold, qsold to save under just "item" which is saved under "items
You should use ->appendChild() on the item node created, not the root which is <items>:
// create child element
$item = $dom->createElement("item");
$dom->appendChild($item);
// create text node
$id = $dom->createElement("id");
$item->appendChild($id); // item->appendChild not $root->appendChild
Should look like this:
$dom = new DOMDocument("1.0");
// create root element
$root = $dom->createElement("Items");
$dom->appendChild($root);
$dom->formatOutput=true;
// create child element
$item = $dom->createElement("item");
$root->appendChild($item); // append to `<Items>`
// create text node
$id = $dom->createElement("id");
$item->appendChild($id); // append to `<item>`
$name = $dom->createElement("name");
$item->appendChild($name); // append to `<item>`
$price = $dom->createElement("price");
$item->appendChild($price); // append to `<item>`
$quantity = $dom->createElement("quantity");
$item->appendChild($quantity); // append to `<item>`
$description = $dom->createElement("description");
$item->appendChild($description); // append to `<item>`
$qonhold = $dom->createElement("qonhold");
$item->appendChild($qonhold); // append to `<item>`
$qsold = $dom->createElement("qsold");
$item->appendChild($qsold); // append to `<item>`
Related
I have wrote this code in PHP to compile an XML file with parameters that are in URL.
But when the XML file is already created instead of adding the new data at the bottom of file inside the root element, overwrite it and delete all old data.
Where is the problem?
I have seen some examples online but I can't figure out how fix it.
I need to verify if file already exist and then add the element?
Or I need to read it and then add again the old elements and new?
I don't know very well dom so I can't figure out
<?php
$FOL = $_GET["FOL"];
$NUM = $_GET["NUM"];
$DAT = $_GET["DAT"];
$ZON = $_GET["ZON"];
$TIP = $_GET["TIP"];
$COM = $_GET["COM"];
$dom = new DOMDocument();
$dom->encoding = 'utf-8';
$dom->xmlVersion = '1.0';
$dom->formatOutput = true;
$xml_file_name = "$NUM.xml";
$xmlString = file_get_contents($xml_file_name);
$dom->loadXML($xmlString);
$loaded_xml = $dom->getElementsByTagName('Territorio');
$territorio_node = $dom->createElement('Territorio');
$child_node_NOM = $dom->createElement('NOM', "$NOM");
$territorio_node->appendChild($child_node_NOM);
$child_node_NUM = $dom->createElement('NUM', "$NUM");
$territorio_node->appendChild($child_node_NUM);
$child_node_DAT = $dom->createElement('DAT', "$DAT");
$territorio_node->appendChild($child_node_DAT);
$child_node_ZON = $dom->createElement('ZON', "$ZON");
$territorio_node->appendChild($child_node_ZON);
$dom->appendChild($territorio_node);
$child_node_TIP = $dom->createElement('TIP', "$TIP");
$territorio_node->appendChild($child_node_TIP);
$child_node_COM = $dom->createElement('COM', "$COM");
$territorio_node->appendChild($child_node_COM);
$dom->appendChild($territorio_node);
$dom->save($FOL.'/'.$xml_file_name);
echo "$xml_file_name creato correttamente";
?>
as per the comment: You should check that the root node of the XML file exists before calling createElement to generate a new one. To do that you can call getElementsByClassName and test whether the first entry is empty
ie: empty( $dom->getElementsByTagName('Territorio')[0] ) sort of thing...
If the root node exists we use that, otherwise add a new root to the document and continue
// check that the querystring has all the required parameters
if( isset(
$_GET['FOL'],
$_GET['NUM'],
$_GET['DAT'],
$_GET['ZON'],
$_GET['TIP'],
$_GET['COM']
)){
// the filename is generated from one of the querystring parameters
// - here the directory used is the same as the script running
$file=sprintf( '%s/%s.xml', __DIR__, $_GET['NUM'] );
// create an empty file if it does not exist
if( !file_exists( $file )){
file_put_contents( $file, '' );
}
clearstatcache();
// create the DOMDocument and set various options
libxml_use_internal_errors( true );
$dom=new DOMDocument('1.0','utf-8');
$dom->strictErrorChecking=false;
$dom->preserveWhiteSpace=true;
$dom->formatOutput=true;
$dom->recover=true;
// load the XML file directly rather than loading a string read from the original file.
$dom->load( $file );
// The ROOT node of the document ... does it exist? if not, create it and add to the DOM.
$root=$dom->getElementsByTagName('Territorio')[0];
if( empty( $root ) ){
$root=$dom->createElement('Territorio');
$dom->appendChild( $root );
}
// I added this part so that you can distinguish easily new elements
$record=$dom->createElement('record');
$root->appendChild( $record );
// add all the querystring parameters within the new record.
$record->appendChild( $dom->createElement('NUM', $_GET["NUM"] ) );
$record->appendChild( $dom->createElement('DAT', $_GET["DAT"] ) );
$record->appendChild( $dom->createElement('ZON', $_GET["ZON"] ) );
$record->appendChild( $dom->createElement('TIP', $_GET["TIP"] ) );
$record->appendChild( $dom->createElement('COM', $_GET["COM"] ) );
$record->appendChild( $dom->createElement('FOL', $_GET["FOL"] ) );
$dom->save( $file );
}
An example of the XML generated:
<?xml version="1.0" encoding="utf-8"?>
<Territorio>
<record>
<NUM>wibble</NUM>
<DAT>25/10/2022</DAT>
<ZON>europe</ZON>
<TIP>total</TIP>
<COM>94</COM>
<FOL>234</FOL>
</record>
<record>
<NUM>wibble</NUM>
<DAT>26/10/2022</DAT>
<ZON>europe</ZON>
<TIP>total</TIP>
<COM>96</COM>
<FOL>238</FOL>
</record>
</Territorio>
In the original code the file is saved to a location defined by another parameter in the querystring ( only just noticed that afterwards ) so rather than
$file=sprintf( '%s/%s.xml', __DIR__, $_GET['NUM'] );
you would likely want to do:
$file=sprintf( '%s/%s.xml', $_GET['FOL'], $_GET['NUM'] );
The root node of an XML document is called document element and here is an property for it. So you can just check if it is undefined. However an document can have only a single document element, so will need to modify the structure of your XML - for example add a "Territori" document element.
Do not use the second argument of the createElement() method or the $nodeValue property. Their escaping is broken - try adding a value with an &. Use $textContent or add a text node.
In modern DOM you can even just append() a string.
$NUM = "NUM";
$DAT = "DAT";
$ZON = "ZON";
$document = new DOMDocument('1.0', 'UTF-8');
// let the parser ignore existing indents
$document->preserveWhiteSpace = false;
$document->loadXML(getXMLString());
// fetch or create document element
$territori = $document->documentElement
?? $document->appendChild($document->createElement('Territori'));
// create/append an item element
$territori
->appendChild(
$territorio = $document->createElement('Territorio')
);
// create/append an element and set its text content
$territorio
->appendChild($document->createElement('NUM'))
->textContent = $NUM;
// create/append an element with a text child node
$territorio
->appendChild($document->createElement('DAT'))
->appendChild($document->createTextNode($DAT));
// create/append an element and a string (DOM Level 3)
$territorio
->appendChild($document->createElement('ZON'))
->append((string)$ZON);
// enable output formatting
$document->formatOutput = true;
echo $document->saveXML();
function getXMLString() {
return <<<'XML'
<?xml version="1.0"?>
<Territori>
<Territorio>
<NUM>NUM</NUM>
<DAT>DAT</DAT>
<ZON>DAT</ZON>
</Territorio>
</Territori>
XML;
}
For a more flexible approach to fetch nodes use Xpath expressions. Here is an example that checks if an Territorio with a specific NUM value exists:
$document = new DOMDocument('1.0', 'UTF-8');
$document->loadXML(getXMLString());
$xpath = new DOMXpath($document);
if ($xpath->evaluate('count(//Territorio[NUM="NUM"]) > 0')) {
echo "Node exists";
}
I have a PHP code that is running well, however not as expected.
F.Y.I: It´s running a function that is collecting submitted data from a form. (piece of code not included here, cause it´s OK).
I need to have 2 fields inside "Dados": name and email, however only email is being recorded.
What should I do? Any clue?
My actual PHP code:
function my_generate_xml($posted_data)
$domDocument = new DOMDocument('1.0', 'ISO-8859-1');
$domDocument->formatOutput = true;
// build maximizer xml file
$xml_root = $domDocument->createElement('moduledata');
$xmlEntity = $domDocument->createElement('entity');
$xmlEntityTN = $domDocument->createAttribute('tablename');
$xmlEntityTN->value = 'Ent';
$xmlEntityFN = $domDocument->createAttribute('formatname');
$xmlEntityFN->value = 'Curriculum';
$xmlEntity->appendChild($xmlEntityTN);
$xmlEntity->appendChild($xmlEntityFN);
$xmlDefine = $domDocument->createElement('define');
$xmlDefine->nodeValue = $posted_data['nome'];
$xmlDefineN = $domDocument->createAttribute('name');
$xmlDefineN->value = 'ParamNome';
$xmlDefine->appendChild($xmlDefineN);
$xmlEntity->appendChild($xmlDefine);
$xmlSiga = $domDocument->createElement('SigaFiles');
$xmlSigaDN = $domDocument->createAttribute('Text');
$xmlSigaDN->value = 'SQG';
$xmlSiga->appendChild($xmlSigaDN);
// create node for current dados
$xml_dados = $domDocument->createElement('Dados');
$domElement = $domDocument->createElement('attribute',$posted_data['nome']);
$domElement = $domDocument->createElement('attribute',$posted_data['email']);
$domAttribute = $domDocument->createAttribute('domainname');
// Value for the created attribute
$domAttribute->value = 'Nome';
$domAttribute->value = 'Email';
$domElement->appendChild($domAttribute);
$xml_dados->appendChild($domElement);
$xmlSiga->appendChild($xml_dados);
$xmlEntity->appendChild($xmlSiga);
$xml_root->appendChild($xmlEntity);
$domDocument->appendChild($xml_root);
Desired XML output format:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<moduledata>
<entity tablename="Ent" formatname="Curriculum">
<define name="ParamNome">Thomas Edison</define>
<SigaFiles Text="SQG">
<Dados>
<attribute domainname="Nome">Thomas Edison</attribute>
<attribute domainname="Email">thomas.edison#gmail.com</attribute>
</Dados>
</SigaFiles>
</entity>
</moduledata>
Actual XML output format:
<?xml version="1.0" encoding="ISO-8859-1"?>
<moduledata>
<entity tablename="Ent" formatname="Curriculum">
<define name="ParamNome">Thomas Edison</define>
<SigaFiles Text="SQG">
<Dados>
<attribute domainname="Email">thomas.edison#gmail.com</attribute>
</Dados>
</SigaFiles>
</entity>
</moduledata>
Actual XML output format: (UPDATED)
<?xml version="1.0" encoding="ISO-8859-1"?>
<moduledata>
<entity tablename="Ent" formatname="Curriculum">
<define name="Thomas Edison">nome</define>
<SigaFiles Text="SQG">
<Dados>
<attribute domainname="Nome">Thomas Edison</attribute>
<attribute domainname="Email">thomas.edison#gmail.com</attribute>
</Dados>
</SigaFiles>
</entity>
</moduledata>
PHP Code (Updated)
<?php
function my_generate_xml($posted_data)
{
$domDocument = new DOMDocument('1.0', 'ISO-8859-1');
$domDocument->formatOutput = true;
// build maximizer xml file
$xml_root = $domDocument->createElement('moduledata');
$xmlEntity = $domDocument->createElement('entity');
$xmlEntityTN = $domDocument->createAttribute('tablename');
$xmlEntityTN->value = 'Ent';
$xmlEntityFN = $domDocument->createAttribute('formatname');
$xmlEntityFN->value = 'Curriculum';
$xmlEntity->appendChild($xmlEntityTN);
$xmlEntity->appendChild($xmlEntityFN);
$xmlDefine = $domDocument->createElement('define');
$xmlDefine->nodeValue = $posted_data['nome'];
$xmlDefineN = $domDocument->createAttribute('name');
$xmlDefineN->value = 'ParamNome';
$xmlDefine->appendChild($xmlDefineN);
$xmlEntity->appendChild($xmlDefine);
$xmlSiga = $domDocument->createElement('SigaFiles');
$xmlSigaDN = $domDocument->createAttribute('Text');
$xmlSigaDN->value = 'SQG';
$xmlSiga->appendChild($xmlSigaDN);
// create node for current dados
$xml_dados = $xmlSiga->appendChild($domDocument->createElement('Dados'));
$domElement = $xml_dados->appendChild($domDocument->createElement('attribute'));
$domElement->appendChild($domDocument->createTextNode($posted_data['nome']));
$domElement->setAttribute('domainname', 'Nome');
$domElement = $xml_dados->appendChild($domDocument->createElement('attribute'));
$domElement->appendChild($domDocument->createTextNode($posted_data['email']));
$domElement->setAttribute('domainname', 'Email');
$domDocument->appendChild($domElement);
$xmlSiga->appendChild($domDocument);
$xmlEntity->appendChild($xmlSiga);
$xml_root->appendChild($xmlEntity);
$domDocument->appendChild($xml_root);
// save it as a file for further processing
$content = chunk_split(base64_encode($domDocument->saveXML()));
$uploads = wp_upload_dir();
$domDocument->save($uploads['basedir'].'/prorh/'.(int)microtime(true).'.xml');
}
?>
Consider reorganizing your routine and append elements after their creation and not save all appendChild calls at the end. Since you reuse the same variable names keep all components (element, attribute, values) together. Recall XML is a tree structure that grows from the root:
// build maximizer xml file
$domDocument = new DOMDocument('1.0', 'ISO-8859-1');
$domDocument->formatOutput = true;
// moduledata root element
$xml_root = $domDocument->createElement('moduledata');
$domDocument->appendChild($xml_root);
// entity element
$xmlEntity = $domDocument->createElement('entity');
$xml_root->appendChild($xmlEntity);
$xmlEntityTN = $domDocument->createAttribute('tablename');
$xmlEntityTN->value = 'Ent';
$xmlEntityFN = $domDocument->createAttribute('formatname');
$xmlEntityFN->value = 'Curriculum';
$xmlEntity->appendChild($xmlEntityTN);
$xmlEntity->appendChild($xmlEntityFN);
// define element
$xmlDefine = $domDocument->createElement('define');
$xmlEntity->appendChild($xmlDefine);
$xmlDefine->nodeValue = $posted_data['nome'];
$xmlDefineN = $domDocument->createAttribute('name');
$xmlDefineN->value = 'ParamNome';
$xmlDefine->appendChild($xmlDefineN);
// SigaFiles element
$xmlSiga = $domDocument->createElement('SigaFiles');
$xmlEntity->appendChild($xmlSiga);
$xmlSigaDN = $domDocument->createAttribute('Text');
$xmlSigaDN->value = 'SQG';
$xmlSiga->appendChild($xmlSigaDN);
// dados element
$xml_dados = $domDocument->createElement('Dados');
$xmlSiga->appendChild($xml_dados);
// attribute child nodes
$domElement = $domDocument->createElement('attribute', $posted_data['nome']);
$domAttribute = $domDocument->createAttribute('domainname');
$domAttribute->value = 'Nome';
$domElement->appendChild($domAttribute);
$xml_dados->appendChild($domElement);
$domElement = $domDocument->createElement('attribute', $posted_data['email']);
$domAttribute = $domDocument->createAttribute('domainname');
$domAttribute->value = 'Email';
$domElement->appendChild($domAttribute);
$xml_dados->appendChild($domElement);
// OUTPUT TREE TO STRING
header("Content-type: text/xml");
echo $domDocument->saveXML();
You override the $domElement variable without appending the node.
// create node for current dados
$xml_dados = $domDocument->createElement('Dados');
$domElement = $domDocument->createElement('attribute',$posted_data['nome']);
$domElement = $domDocument->createElement('attribute',$posted_data['email']);
$domAttribute = $domDocument->createAttribute('domainname');
I suggest nesting the create* calls inside appendChild() calls.
// create node for current dados
$xml_dados = $xmlSiga->appendChild($domDocument->createElement('Dados'));
$domElement = $xml_dados->appendChild($domDocument->createElement('attribute'));
$domElement->appendChild($domDocument->createTextNode($posted_data['nome']));
$domElement->setAttribute('domainname', 'Nome');
$domElement = $xml_dados->appendChild($domDocument->createElement('attribute'));
$domElement->appendChild($domDocument->createTextNode($posted_data['email']));
$domElement->setAttribute('domainname', 'Email');
You do not need to create attributes as nodes, DOMElement::setAttribute() works just fine for that. But you should create text content as nodes. The second argument of DOMDocument::createElement() is broken and escapes only some special characters.
i want to replace value of commented tags in xml file..how can i replace it using php ..given is file.xml
<SyncOpportunity_Input>
<SendConfirmationEmail/>
<UpdateToken/>
<CallingSystem>WS-TEST</CallingSystem>
<KeepLocking/>
<Error_spcCode/>
<EmailAddrOverwrite/>
<Opportunity>
//<IntegrationId>12</IntegrationId>
//<LoanWriterId>13</LoanWriterId>
//<Description>NA</Description>
<Applicant>
<integratedid1>28</integratedid1>
<FirstName>pri</FirstName>
<LastName>kj</LastName>
</Applicant>
<Property>
<integratedid>2</integratedid>
<Title>Mr</Title>
<DateOfBirth>1999-11-11</DateOfBirth>
</Property>
<Ownership>
<integratedid1>28</integratedid1>
<OwnershipPercentage>100</OwnershipPercentage>
</Ownership>
</Opportunity>
</SyncOpportunity_Input>
i dont want to create node each time.. i just want to replace the value of child node..as i am appending other tags dynamically using php.
here is my function.php file where I have appended other tags,where i have get tags and then created child nodes and the value of each tags is coming from our php form.As well each time we require to delete previous data.
$xml = new DOMDocument('1.0', 'utf-8');
$xml->formatOutput = true;
$xml->preserveWhiteSpace = false;
$nodesToDelete=array();
$pnodesToDelete=array();
//echo $fname;
$xml->load('file.xml');
$nodesToDelete=array();
$IntegrationId = rand(1,19);
$IntegrationId1 = rand(10,30);
$IntegrationId2 = rand(20,40);
$element = $xml->getElementsByTagName('Applicant')->item(0);
$pelement = $xml->getElementsByTagName('Property')->item(0);
$FirstName = $element->getElementsByTagName('FirstName')->item(0);
$LastName = $element->getElementsByTagName('LastName')->item(0);
//echo $timestamp;
//$oelement = $xml->getElementsByTagName('Opportunity');
$oelement = $xml->getElementsByTagName('Ownership')->item(0);;
$ownItem= $xml->createElement('Ownership');
$ownItem->appendChild($xml->createElement('integratedid1',$IntegrationId1 ));
$ownItem->appendChild($xml->createElement('OwnershipPercentage',100));
//$oItem->appendChild($xml->createElement('integratedid2',$IntegrationId2));
$newItem= $xml->createElement('Applicant');
$newItem->appendChild($xml->createElement('integratedid1',$IntegrationId1 ));
$newItem->appendChild($xml->createElement('FirstName', $_POST['fld_2260636']));
$newItem->appendChild($xml->createElement('LastName', $_POST['fld_4322743']));
$pnewItem= $xml->createElement('Property');
$pnewItem->appendChild($xml->createElement('integratedid',$IntegrationId ));
$pnewItem->appendChild($xml->createElement('Title', $_POST['fld_4755553']));
$pnewItem->appendChild($xml->createElement('DateOfBirth', $_POST['fld_1151367']));
//echo $newItem;
$xml->getElementsByTagName('Opportunity')->item(0)->appendChild($newItem);
$xml->getElementsByTagName('Opportunity')->item(0)->appendChild($pnewItem);
$xml->getElementsByTagName('Opportunity')->item(0)->appendChild($ownItem);
$nodesToDelete[]=$element;
$pnodesToDelete[]=$pelement;
$onodesToDelete[]=$oelement;
I have a XML file and I'm trying to insert a new node between two others with PHP script.
XML file:
<playlistLog>
<hour>
<track>
<type>take</type>
<url>URL</url>
<title>1473869236.wav</title>
<mix>0</mix>
</track>
(...)
</hour>
</playlistLog>
PHP file:
$xmldoc = new DOMDocument();
$xmldoc->load('../logs/log14-09-2016.xml');
$elem = $xmldoc->getElementsByTagName("track");
$track = $xmldoc->createElement('track');
$type = $xmldoc->createElement('type', 'take');
$track->appendChild($type);
$url = $xmldoc->createElement('url', 'url');
$track->appendChild($url);
$title = $xmldoc->createElement('title', 'title');
$track->appendChild($title);
$mix = $xmldoc->createElement('mix', 'mix');
$track->appendChild($mix);
$xmldoc->documentElement->insertBefore($track,$elem[660]);
$xmldoc->save('../logs/log14-09-2016.xml');
I'm trying to insert the new node before "track" tag number 660 but when I try to open the php file it doesn't work at all.
Can anybody tell me what I am doing wrong?
SOLUTION:
After #ThW response I change a bit what he wrotes and finally the code is doing right:
$document = new DOMDocument();
$document->preserveWhiteSpace = FALSE;
$document->load('../logs/log14-09-2016.xml');
$xpath = new DOMXpath($document);
$previousTrack = $xpath->evaluate('/playlistLog/hour/track')->item(659);
$newTrack = $previousTrack->parentNode->insertBefore($document->createElement('track'),$previousTrack);
$newTrack
->appendChild($document->createElement('type'))
->appendChild($document->createTextNode('take'));
$document->formatOutput = TRUE;
echo $document->save('../logs/log14-09-2016.xml');
$elem[660] is the 661st element node with the tag name track. But its parent node is not the document element. Here is another hour ancestor between. The node you're providing to insertBefore() has a different parent then the node you're adding the new element to.
You can use the $parentNode property to make sure that you append to that node.
Additionally I suggest using Xpath to fetch the track node.
$xml = <<<'XML'
<playlistLog>
<hour>
<track>
<type>take</type>
<url>URL</url>
<title>1473869236.wav</title>
<mix>0</mix>
</track>
</hour>
</playlistLog>
XML;
$document = new DOMDocument();
$document->preserveWhiteSpace = FALSE;
$document->loadXml($xml);
$xpath = new DOMXpath($document);
$previousTrack = $xpath->evaluate('/playlistLog/hour/track[1]')->item(0);
$newTrack = $previousTrack
->parentNode
->insertBefore(
$document->createElement('track'),
$previousTrack
);
$newTrack
->appendChild($document->createElement('type'))
->appendChild($document->createTextNode('take'));
$document->formatOutput = TRUE;
echo $document->saveXml();
I'm using DOMDocument class of PHP to create a xml file, my code is:
$xmlObject = new DOMDocument('1.0', 'utf-8');
//root node -- books
$books = $xmlObject->createElement('books');
//book node
$book = $xmlObject->createElement('book');
//book node's attribute -- index
$index = new DOMAttr('index', '1');
$book->appendChild($index);
//name node
$name = $xmlObject->createElement('name', 'Maozedong');
//name node's attribute -- year
$year = new DOMAttr('year', '1920');
$name->appendChild($year);
$book->appendChild($name);
//story node
$story = $xmlObject->createElement('story');
$title = $xmlObject->createElement('title', 'Redrevolution');
$quote = $xmlObject->createElement('quote', 'LeaveoffHunan');
$story->appendChild($title);
$story->appendChild($quote);
$book->appendChild($story);
$books->appendChild($book);
if ($xmlObject->save('xml/books.xml') != false){
echo 'success';
}else{
echo 'error';
}
The content of books.xml is only one line:
<?xml version="1.0" encoding="utf-8"?>
the other node is non-existent. Are there any errors in my code?
I forget append the books node to $xmlObject.
add:
$xmlObject->appendChild($books);