Php:Proble when i convert in xml - php

I want my arElemt(gurl and gname) put in . Example and problem2 = when i write g:url or g:name = Error... php7.2* and now example now now i have this construction
-rss
---title
---link
---description
---gurl
---gname
i want now i have this construction
-rss
---title
---link
---description
---gurl
---gname
---gurl
---gname
---gurl
---gname i want
-rss
---title
---link
---description
---item
-----gurl
-----gname
---item
-----gurl
-----gname
---item
-----gurl
-----gname
---item
-----gurl
-----gname
header("Content-type: text/xml; charset=utf-8");
$dom = new DOMDocument('1.0','utf-8');
$root = $dom->createElement('rss');
$dom->appendChild($root);
$title = $dom->createElement('title', 'test');
$root->appendChild($title );
$link = $dom->createElement('link', 'test');
$root->appendChild($link );
$description = $dom->createElement('description', 'test');
$root->appendChild($description );
$root = $item->createElement('item');
while($arElement = $rsElements->GetNext())
{
$url = $dom->createElement("gurl", $surl.$arElement[DETAIL_PAGE_URL]);
$item->appendChild($url );
$name = $dom->createElement("gname", $arElement[NAME]);
$root->appendChild($name );
}
echo $dom->saveXML();
$dom->save($file_name); // save as file

Here is a big difference between gurl and g:url. gurl is not an valid RSS tag afaik. g:url is an url element inside a defined namespace.
The g from g:url is a namespace prefix. It references a namespace definition. Look for a xmlns:g attribute in examples or for the namespace URI in the documentation of the format. The g is an alias for the value of that attribute. A parser resolves that to the URI internally. All the following nodes can be read as {urn:example:namespace}url.
<g:url xmlns:g="urn:example:namespace"/>
<g2:url xmlns:g2="urn:example:namespace"/>
<url xmlns="urn:example:namespace"/>
RSS itself is just wellformed XML, it uses no namespace. But it can contain other XML formats that use namespaces (MediaRSS, ...).
To create an element with a namespace use the method DOMDocument::createElementNS(). This will automatically add the namespace definition if needed. However if do not use the namespace for the document element it will be added multiple times. You can set the namespace definition as an attribute of the reserved XMLNS namespace.
$data = ['one', 'two'];
// the namespace for namespace definitions
const XMLNS_XMLNS = 'http://www.w3.org/2000/xmlns/';
// namespace referenced by prefix g?
const XMLNS_G = 'urn:example:namespace';
$document = new DOMDocument('1.0','utf-8');
$rss = $document->appendChild(
$document->createElement('rss')
);
// add the namespace definition to the document element
$rss->setAttributeNS(XMLNS_XMLNS, 'xmlns:g', XMLNS_G);
// create + append element node, set its text content
$rss->appendChild(
$document->createElement('title')
)->textContent = 'test';
foreach ($data as $value) {
$item = $rss->appendChild(
$document->createElement('item')
);
// create and append an element with the namespace
$item->appendChild(
$document->createElementNS(XMLNS_G, 'g:url')
)->textContent = 'http://example.com/page?'.$value;
}
$document->formatOutput = TRUE;
echo $document->saveXML();
Output:
<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:g="urn:example:namespace">
<title>test</title>
<item>
<g:url>http://example.com/page?one</g:url>
</item>
<item>
<g:url>http://example.com/page?two</g:url>
</item>
</rss>
Hint 1: DOMNode::appendChild() returns the appended node. It is possible to nest the create call.
Hint 2: DOMNode::$textContent allows to read/write the text content of a node and escapes properly.

const XMLNS_XMLNS = 'http://www.w3.org/2000/xmlns/';
// namespace referenced by prefix g?
const XMLNS_G = 'urn:example:namespace';
$document = new DOMDocument('1.0','utf-8');
$rss = $document->appendChild(
$document->createElement('rss')
);
// add the namespace definition to the document element
$rss->setAttributeNS(XMLNS_XMLNS, 'xmlns:g', XMLNS_G);
// create + append element node, set its text content
$rss->appendChild(
$document->createElement('title')
)->textContent = 'test';
while($arElement = $rsElements->GetNext())
{
$item = $rss->appendChild(
$document->createElement('item')
);
$item->appendChild(
$document->createElementNS(XMLNS_G, 'g:url')
)->textContent = $surl.$arElement["DETAIL_PAGE_URL"];
$item->appendChild(
$document->createElementNS(XMLNS_G, 'g:name')
)->textContent = $arElement["NAME"];
}

Related

How to add a child in xml without overwrite using php dom?

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";
}

generating sitemap with DOMDocument : missing AttributeNode in the output

im trying to generate a sitemap.xml , here is simplified version of my code
$dom = new \DOMDocument();
$dom->encoding = 'utf-8';
$dom->xmlVersion = '1.0';
$dom->formatOutput = true;
$xml_file_name = './sitemap.xml';
$urlset = $dom->createElement('urlset');
$attr_ = new \DOMAttr('xmlns:xsi', "http://www.w3.org/2001/XMLSchema-instance");
$urlset->setAttributeNode($attr_);
$url_node = $dom->createElement('url');
$url_node_loc = $dom->createElement('loc', 'http://localhost' );
$url_node->appendChild($url_node_loc);
$url_node_lastmod = $dom->createElement('lastmod', '2021-08-03T22:17:47+04:30' );
$url_node->appendChild($url_node_lastmod);
$urlset->appendChild($url_node);
$dom->appendChild($urlset);
$dom->save($xml_file_name);
dd('done');
here is the output in my sitemap.xml
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<urlset>
<url>
<loc>http://localhost</loc>
<lastmod>2021-08-03T22:17:47+04:30</lastmod>
</url>
</urlset>
i need to add some attributes to my urlset tag , here is how i've did it
$attr_ = new \DOMAttr('xmlns:xsi', "http://www.w3.org/2001/XMLSchema-instance");
$urlset->setAttributeNode($attr_);
but for some reason this doesn't show up in my sitemap file , urlset has no attributes
Use setAttribute() instead of setAttributeNode().
$urlset->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
This will not be a valid sitemap. Sitemaps use an XML namespace (https://www.sitemaps.org/protocol.html)
To create nodes with namespaces you should use the namespace aware DOM methods with the *NS suffix. This will add namespace definitions as needed.
xmlns:xsi is a namespace definition. They can be considered attributes nodes in the reserved namespace {http://www.w3.org/2000/xmlns/}.
$xmlns = [
'sitemap' => 'http://www.sitemaps.org/schemas/sitemap/0.9',
'xmlns' => 'http://www.w3.org/2000/xmlns/',
'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
];
$document = new \DOMDocument('1.0', 'utf-8');
$document->formatOutput = true;
$urlset = $document->appendChild(
$document->createElementNS($xmlns['sitemap'], 'urlset')
);
// explict namespace definition
$urlset->setAttributeNS(
$xmlns['xmlns'], 'xmlns:xsi', $xmlns['xsi']
);
$url_node = $urlset->appendChild(
$document->createElementNS($xmlns['sitemap'], 'url')
);
$url_node
->appendChild($document->createElementNS($xmlns['sitemap'], 'loc'))
->textContent = 'http://localhost';
$url_node
->appendChild($document->createElementNS($xmlns['sitemap'], 'lastmod'))
->textContent = '2021-08-03T22:17:47+04:30';
echo $document->saveXML();
Output:
<?xml version="1.0" encoding="utf-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<url>
<loc>http://localhost</loc>
<lastmod>2021-08-03T22:17:47+04:30</lastmod>
</url>
</urlset>

Add namespace attribute to xml node in php

Following is the node I am trying to create in my XML -
<?xml version="1.0" standalone="no" ?>
<manifest identifier="com.scorm.golfsamples.contentpackaging.multioscosinglefile.20043rd"
version="1"
xmlns="http://www.imsglobal.org/xsd/imscp_v1p1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:adlcp="http://www.adlnet.org/xsd/adlcp_v1p3"
xmlns:adlseq="http://www.adlnet.org/xsd/adlseq_v1p3"
xmlns:adlnav="http://www.adlnet.org/xsd/adlnav_v1p3"
xmlns:imsss="http://www.imsglobal.org/xsd/imsss"
xsi:schemaLocation="http://www.imsglobal.org/xsd/imscp_v1p1 imscp_v1p1.xsd
http://www.adlnet.org/xsd/adlcp_v1p3 adlcp_v1p3.xsd
http://www.adlnet.org/xsd/adlseq_v1p3 adlseq_v1p3.xsd
http://www.adlnet.org/xsd/adlnav_v1p3 adlnav_v1p3.xsd
http://www.imsglobal.org/xsd/imsss imsss_v1p0.xsd">
Code is working fine for identifier and version attribute but unable to generate it with namespace like xmlns="http://www.imsglobal.org/xsd/imscp_v1p1"
Tried this code from here but unable to make it :(
$doc = new DOMDocument( '1.0' );
$doc->loadXML( $source );
// (1) We just create a "namespace'd" attribute without appending it to any element.
$attr_ns = $doc->createAttributeNS( '{namespace_uri_here}', 'example:attr' );
print $doc->saveXML() . "\n";
Codepad Link - http://codepad.org/uLJc4hpP
Full code -
//creating an XML document
$dom = new DOMDocument('1.0');
$dom->xmlStandalone = false;
//create element manifest
$manfiestNode = $dom->createElement('manifest',"");
//create attribute identifier
$manfiestNodeAttr = $dom->createAttribute('identifier');
//value for the manifest node identifier value
$date = new DateTime();
$manfiestNodeAttr->value = 'course_'.date_format($date,'U');
//append attribute to the manifest element
$manfiestNode->appendChild($manfiestNodeAttr);
//create attribute with an associated namespace
$nodeAttr = $manfiestNode->createAttributeNS('{namespace_uri_here}', 'example:attr');
//append namespace to the manifest element
$nodeAttr->appendChild($manfiestNode);
//append manifest element to the document
$dom->appendChild($manfiestNode);
var_dump($dom->saveXML());
Let me know what I am conceptually doing wrong and how could I make it working.
I tried by changing $manfiestNode to $dom in line 20[codepad link] but still no luck :(.
Error-
Fatal error: Call to undefined method DOMElement::createAttributeNS()
on line 20
Try with createAttribute like following
$dom = new DOMDocument('1.0','UTF-8');
// root manifest
$root = $dom->appendChild($dom->createElement('manifest'));
// identifier
$date = new DateTime();
$manfiestNodeAttr_value = 'course_'.date_format($date,'U');
$root->appendChild($dom->createAttribute('identifier'))->appendChild($dom->createTextNode($manfiestNodeAttr_value));
// version
$version = 1;
$root->appendChild($dom->createAttribute('version'))->appendChild($dom->createTextNode($version));
// xmlns:xsi
$root->appendChild($dom->createAttribute('xmlns:xsi'))->appendChild($dom->createTextNode("http://www.w3.org/2001/XMLSchema-instance"));
print_r($dom->saveXML());
Demo Codepad: http://codepad.org/zgug0Gl3

about php 5.x create xml by dom document

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);

PHP DOM XML - Create Multiple Namespace Attributes?

I'm working on some PHP to create XML from a database using the DOM extension.
Basically, I need to create a NameSpace and add 3 attributes to it:
<NameSpaceName xmlns="uri:xxx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="uri:xxx">
The full code i've written is below:
include_once("includes/connect.php");
$sql = ("SELECT * FROM tableName");
$query = mysql_query($sql) or die("Error: " . mysql_error());
// create a new XML document
$doc = new DomDocument('1.0', 'UTF-8');
// create root node
$root = $doc->createElementNS('uri:xxx', 'PayerRecords');
$root = $doc->appendChild($root);
$root->setAttributeNS('http://www.w3.org/2000/xmlns/' ,'xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
$root->setAttributeNS('http://www.w3.org/2000/xmlns/' ,'xsi:schemaLocation', 'uri:xxx');
// process one row at a time
while($row = mysql_fetch_assoc($query)) {
// add node for each row
$occ = $doc->createElement('Content');
$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);
} // foreach
} // while
// get completed xml document
$xml_string = $doc->saveXML();
echo $xml_string;
But when I execute the above I get this error:
Fatal error: Uncaught exception
'DOMException' with message 'Namespace
Error' in
xml.php:21
Stack trace: #0
xml.php(21):
DOMElement->setAttributeNS('http://www.w3.o...', 'xsi:schemaLocat...',
'uri:xxx...') #1 {main} thrown
in
xml.php
on line 21
Line 21 is the second 'setAttributeNS' line.
Can anyone see where i'm going wrong?
schemaLocation is not declared in the namespace http://www.w3.org/2000/xmlns/ but in http://www.w3.org/2001/XMLSchema-instance
<?php
// create a new XML document
$doc = new DomDocument('1.0', 'UTF-8');
// create root node
$root = $doc->createElementNS('http://xxx', 'PayerRecords');
$root = $doc->appendChild($root);
$root->setAttributeNS('http://www.w3.org/2000/xmlns/' ,'xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
$root->setAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation', 'http://xxx');
echo $doc->savexml();
prints
<?xml version="1.0" encoding="UTF-8"?>
<PayerRecords xmlns="http://xxx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xxx"/>
I didn't quite get it the first time so I'm posting my answer in more detail. Maybe someone finds this helpful.
// create DOM document
$xml = new DomDocument('1.0', 'UTF-8');
// create root element
$el = $xml->createElementNS('http://namespaceA/url/here/', 'rootelement');
// to be able to add new namespaces we must first add namespace 'xsi'
// third parameter is important (use your main namespace with .xsd)
$root->setAttributeNS(
'http://www.w3.org/2001/XMLSchema-instance',
'xsi:schemaLocation',
'http://namespaceA/url/here/ http://namespaceA/xsdfile/here.xsd');
// add new namespace
$el->setAttributeNS(
'http://www.w3.org/2000/xmlns/',
'xmlns:namespaceB',
'http://namespaceB/url/here/');
// add root element to DOM
$xml->appendChild($el);
This mail archive message was very helpful: http://www.mail-archive.com/php-general#lists.php.net/msg135362.html.
replace line 21 with
$root->setAttributeNS(
'http://www.w3.org/2001/XMLSchema-instance',
'xsi:schemaLocation',
'http://xxx http://xxx/xxx.xsd'
);
xsi:schemaLocation is not defined in the http://www.w3.org/2000/xmlns/ or your namespace, but in xsi. so you have to use the (complete) xsi namespace uri as the first parameter.
and: you don't need to call setAttributeNS() twice: the single line above generates both the xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" and xsi:schemaLocation="http://xxx http://xxx/xxx.xsd" attributes.

Categories