I'm retrieving a set of contact records from a database query, and I then need to generate an XML response that is returned to the browser.
The PHP loop that retrieves the records looks like this:
foreach($contacts as $contact){
$firstName = $record->getField('first') ;
$lastName = $record->getField('last') ;
$recnum++; }
and the XML I need to generate looks like this:
<?xml version="1.0" encoding="utf-8"?>
<contacts>
<contact>
<first_name>Penny</first_name>
<last_name>Lancaster</last_name>
</contact>
<contact>
<first_name>Geoff</first_name>
<last_name>McDermott</last_name>
</contact>
</contacts>
I've been able to create a single hardcoded XML response before using:
$doc = new DOMDocument('1.0', 'utf-8');
$doc->formatOutput = true;
$root = $doc->createElement('error');
$doc->appendChild($root);
$desc = $doc->createElement('description', $error);
$root->appendChild($desc);
echo $doc->saveXML();
but I can't work out the syntax to incorporate this into a loop and generate the XML dynamically.
It's pretty simple:
$doc = new DOMDocument('1.0', 'utf-8');
$doc->formatOutput = true;
$contactsElement = $doc->createElement('contacts');
foreach($contacts as $contact){
// your loop, is working? What is $record?
$firstName = $record->getField('first') ;
$lastName = $record->getField('last') ;
$recnum++; // is useful for something?
$contactElement = $doc->createElement('contact');
$firstNameElement = $doc->createElement('first_name', $firstName);
$lastNameElement = $doc->createElement('last_name', $lastName);
$contactElement->appendChild($firstNameElement);
$contactElement->appendChild($lastNameElement);
$contactsElement->appendChild($contactElement);
}
echo $doc->saveXML();
Related
Is there a why to do this? I'm new on create DomDocument. Thank you
<!DOCTYPE Data SYSTEM "http://data.data.org/schemas/data/1.234.1/data.dtd"> <Data payloadID = "123123123131231232323" timestamp = "2015-06-10T12:59:09-07:00">
$aribaXML = new DOMImplementation;
$dtd = $aribaXML->createDocumentType('cXML', '', 'http://xml.cxml.org/schemas/cXML/1.2.014/cXML.dtd');
$dom = $aribaXML->createDocument('', '', $dtd);
Here are two ways in DOM to create a new document in PHP. If you don't need the DTD you can directly create an instance of the DOMDocument class.
$document = new DOMDocument('1.0', "UTF-8");
$document->appendChild(
$cXML = $document->createElement('cXML')
);
echo $document->saveXML();
Output:
<?xml version="1.0" encoding="UTF-8"?>
<cXML/>
For a document with a DTD your approach was correct.
$implementation = new DOMImplementation;
$dtd = $implementation->createDocumentType(
'cXML', '', 'http://xml.cxml.org/schemas/cXML/1.2.014/cXML.dtd'
);
$document = $implementation->createDocument("", "cXML", $dtd);
$document->encoding = 'UTF-8';
$cXML = $document->documentElement;
echo $document->saveXML();
Output:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE cXML SYSTEM "http://xml.cxml.org/schemas/cXML/1.2.014/cXML.dtd">
After the initial bootstrap you use methods of the $document to create nodes and append them.
// set an attribute on the document element
$cXML->setAttribute('version', '1.1.007');
// xml:lang is a namespaced attribute in a reserved namespace
$cXML->setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:lang', 'en-US');
// nested elements
// create a node, store it for the next call and append it
$cXML->appendChild(
$header = $document->createElement('Header')
);
$header->appendChild(
$from = $document->createElement('From')
);
$from->appendChild(
$credential = $document->createElement('Credential')
);
// "Identity" has only a text node so we don't need to store it for later
$credential->appendChild(
$document->createElement('Identity')
)->textContent = '83528721';
// format serialized XML string
$document->formatOutput = TRUE;
echo $document->saveXML();
Output:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE cXML SYSTEM "http://xml.cxml.org/schemas/cXML/1.2.014/cXML.dtd">
<cXML version="1.1.007" xml:lang="en-US">
<Header>
<From>
<Credential>
<Identity>83528721</Identity>
</Credential>
</From>
</Header>
</cXML>
$xml = new DomDocument('1.0');
$xml->formatOutput = true;
$works = $xml->createElement("works");
$xml->appendChild($works);
$work = $xml->createElement("work");
$work->setAttribute("id",1);
$works->appendChild($work);
$xml->save("storage/document.xml") or die("Error, Unable to create XML File");
Say I have an XML file like this.
<users>
<user>
<username>desbest</username>
<email>desbest#example.com</email>
<password>testpass1</password>
</user>
<user>
<username>demo</username>
<email>nobody#example.com</email>
<password>demo</password>
</user>
</users>
How do I use XPath to select the desbest user, then use php to edit the password under the desbest user, and save it as a file?
I have searched Google and Stack Overflow and I haven't found the answer.
Here is my current code.
// print_r($xml);
$newpass = "mynewpass";
// $newpass = password_hash($newpass, PASSWORD_DEFAULT);
$nodes = $xml->xpath(sprintf(" //users/user[(username = \"$myusername\")] "));
// print_r($nodes);
// $nodes[0]->password = "$newpass";
$domnode = dom_import_simplexml($nodes[0]);
$nodepath = $domnode->getNodePath();
// $xml = $xml->$nodepath->password = $newpass;
// $danodepath = $nodes[0]->getNodePath();
// print_r($nodes);
// $xml->users->user["(username = \"$myusername\")"] = "$newpass";
print_r($xml);
echo "<hr>";
print_r($nodepath);
You can achieve this just with SimpleXML - you don't need to involve DOMDocument at all.
The xpath method returns the <user> element you're looking for. You can then modify it simply by updating the password property (or add new ones, or attributes, etc). This updates the underlying SimpleXMLElement object, which you can then write back to the file as a string using asXML.
$filename = 'file.xml';
$sxml = simplexml_load_file($filename);
$username = "desbest";
$user = $sxml->xpath("./user[./username = '{$username}']")[0];
$user->password = 'testpassCHANGED';
file_put_contents($filename, $sxml->asXML());
See https://eval.in/923654 for an example
Example with DOMDocument:
$source = '<users>
<user>
<username>desbest</username>
<email>desbest#example.com</email>
<password>testpass1</password>
</user>
<user>
<username>demo</username>
<email>nobody#example.com</email>
<password>demo</password>
</user>
</users>';
$dom = new DOMDocument();
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->loadXML($source);
$xpath = new DOMXPath($dom);
$myusername = htmlspecialchars("desbest", ENT_XML1 | ENT_QUOTES, 'UTF-8');
$expression = sprintf('/users/user[(username="%s")]', $myusername);
$users = $xpath->query($expression);
if($users->length) {
$user = $users->item(0);
$password = $xpath->query('password', $user)->item(0);
$password->nodeValue = 'new password';
}
file_put_contents('filename.xml', $dom->saveXML());
I have a question: I am trying to create a XML file using DomDocument and I would like to have this output:
<?xml version="1.0" encoding="UTF-8"?>
<winstrom version="1.0">
<main_tag>
<child_tag>example</child_tag>
</main_tag>
<winstrom>
The problem is with the second row - if I write it as below then the output is "Invalid Character Error". I guess it is not allowed to have space characters there... However I need it like this, so what are the options?
$dom = new DomDocument('1.0', 'UTF-8');
$root = $dom->createElement('winstrom version=1.0');
$dom->appendChild($root);
$item = $dom->createElement('hlavni_tag');
$root2->appendChild($item);
$text = $dom->createTextNode('example');
$item->appendChild($text);
$dom->formatOutput = true;
echo $dom->saveXML();
There seems to be a misunderstanding of what an XML element is and how it differs from attributes.
Try this code:
<?php
$dom = new DomDocument('1.0', 'UTF-8');
$root = $dom->createElement('winstrom');
$root->setAttribute("version","1.0");
$dom->appendChild($root);
$root2 = $dom->createElement("main_tag"); //You forgot this part
$root->appendChild($root2);
$item = $dom->createElement('hlavni_tag'); //Should it be "child_tag"?
$root2->appendChild($item);
$text = $dom->createTextNode('example');
$item->appendChild($text);
$dom->formatOutput = true;
echo $dom->saveXML();
I'm generating some XML from a database query as follows:
$doc = new DOMDocument('1.0', 'utf-8');
$doc->formatOutput = true;
$contactsElement = $doc->createElement('contacts');
$doc->appendChild($contactsElement);
foreach($contacts as $contact){
$firstName = $contact->getField('first') ;
$lastName = $contact->getField('last') ;
$contactElement = $doc->createElement('contact');
$firstNameElement = $doc->createElement('first_name', $firstName);
$lastNameElement = $doc->createElement('last_name', $lastName);
$contactElement->appendChild($firstNameElement);
$contactElement->appendChild($lastNameElement);
$contactsElement->appendChild($contactElement);
}
echo $doc->saveXML();
This is working well but it is generating an additional line after the closing at the end. Here's an example:
<?xml version="1.0" encoding="utf-8"?>
<contacts>
<contact>
<first_name>Penny</first_name>
<last_name>Lancaster</last_name>
</contact>
<contact>
<first_name>Geoff</first_name>
<last_name>McDermott</last_name>
</contact>
</contacts>
// blank line is here
I can't see what could be causing this or if there's a syntax change I need to make - any suggestions as to how to prevent the trailing blank line from appearing in the generated XML?
Don't know why there is a trailing new line, but you can solve it with this:
echo trim($doc->saveXML());
I seem to have a small problem, whenever i insert information via a form into my XML file, it adds the information directly IN the previous's entry's child, instead of creating a new child, for the entry, i get something like THIS:
<people>
<person>
<name>Lighty</name>
<age>17</age>
<sex>M</sex>
<comment>iets</comment>
<name>Darky</name><age>22</age><sex>F</sex><comment>things</comment></person>
While i need to have something, that would look like THIS:
<people>
<person>
<name>Lighty</name>
<age>17</age>
<sex>M</sex>
<comment>iets</comment>
</person>
<person>
<name>Darky</name>
<age>22</age>
<sex>F</sex>
<comment>iets</comment>
</people>
i tried using the "$xml->formatOutput = true;" line, but it would just add the child formatOutput with 1 filled in, a complete fail.
Any idea what im doing wrong? here is m PHP Code:
<?php
echo ('Script started');
//making sure the script only runs when you use a post
if ($_SERVER["REQUEST_METHOD"] == "POST") {
echo ('-Post accepted');
//Load XML File into variable
$xml = simplexml_load_file("phptest3.xml");
echo ('-XML Loaded');
//Connect form to Variables
$name = $_POST['name'];
$age = $_POST['age'];
$sex = $_POST['sex'];
$comment = $_POST['comment'];
echo ('-Vars connected');
//Function to strip items that are not needed to prevend XSS/Injections
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
echo ('-Injections stripped');
//Create new children in XML file and Connect the from data to the corresponding XML entries
$xml->formatOutput = true;
$xml->people[0];
$xml->people->addChild('person');
$xml->person->addChild('name', $name);
$xml->person->addChild('age', $age);
$xml->person->addChild('sex', $sex);
$xml->person->addChild('comment', $comment);
echo ('-Data inserted');
//Save current data to XML file...
$xml->savexml('phptest3.xml');
echo ('-saved');
}
echo ('-Script ended.');
?>
You can do this with a combination of SimpleXMLElement and DOMDocument.
This is how I did it:
<pre>
<?php
// Orignal XML - Starting Empty
$xmlStr = "<?xml version='1.0' standalone='yes'?>
<people></people>";
// Load XML
$people = new SimpleXMLElement($xmlStr);
// Debug (Before Add)
echo "<b>Before</b> Add\r\n";
print_r($people);
echo "<hr>\r\n\r\n";
// Add First Person
$newPerson = $people->addChild('person');
$newPerson->addChild('name', 'Lighty');
$newPerson->addChild('age', 17);
$newPerson->addChild('sex', 'M');
$newPerson->addChild('comment', 'iets');
// Debug (After Add)
echo "<b>After</b> Add\r\n";
print_r($people);
echo "<hr>\r\n\r\n";
// Output Modified XML With Formatting
$dom = new DOMDocument;
$dom->preserveWhiteSpace = false;
$dom->loadXML($people->asXML());
$dom->formatOutput = true;
echo $dom->saveXml();
?>
Browser Outout:
Formatted XML Output:
<?xml version="1.0" standalone="yes"?>
<people>
<person>
<name>Lighty</name>
<age>17</age>
<sex>M</sex>
<comment>iets</comment>
</person>
</people>
Hope this helps.