I'm using SimpleXMLElement for create datafeed page: Here the code:
$xml = new SimpleXMLElement("<Products />");
foreach ($products as $pro) {
$track = $xml -> addChild('Product');
$track -> addChild('simple_sku', "<![CDATA[ ABC ]]>");
}
Header('Content-type: text/xml');
print($xml -> asXML());
and the output:
<Products>
<Product>
<simple_sku><![CDATA[ ABC ]]></simple_sku>
</Product>
</Products>
I want to know how to turn output into format like this:
<Products>
<Product>
<simple_sku>
<![CDATA[ ABC ]]>
</simple_sku>
</Product>
<Products>
Thanks you a lot.
It's not possible with SimpleXML so I advice you to use DOMDocument.
Usage example:
$dom = new DOMDocument('1.0');
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->loadXML($simpleXml->asXML());
Related
I am trying to create an xml dynamically using domDocument.
What I would like to obtain is following:
<?xml version="1.0"?>
<books>
<book>
<content>
<name><![CDATA[dddd]]></name>
</content>
</book>
</books>
Unfortunatelly the script below does not show the output as excepted.
$xml = new DOMDocument('1.0');
$xml->formatOutput = true;
$books = $xml->createElement('books');
$xml->appendChild($books);
$book = $xml->createElement('book');
$books->appendChild($book);
$inside = $xml->createElement('content');
$book->appendChild($inside);
$xml->appendChild($inside)->appendChild($xml->createElement('name'))->appendChild($xml->createCDataSection('dddd'));
echo '<xmp>'.$xml->saveXML().'</xmp>';
This is the output
<?xml version="1.0"?>
<books>
<book>
<content>
<name><![CDATA[dddd]]></name>
<lastname><![CDATA[dddd]]></lastname>
....
</content>
I do not know how to use createCDataSection().
Like this?
$xml = new DOMDocument('1.0');
$xml->formatOutput = true;
$books = $xml->createElement('books');
$xml->appendChild($books);
$book = $xml->createElement('book');
$books->appendChild($book);
$content = $xml->createElement('content');
$book->appendChild($content);
$name = $xml->createElement('name');
$content->appendChild($name);
$name->appendChild($xml->createCDataSection('dddd'));
echo '<xmp>'.$xml->saveXML().'</xmp>';
I have an XML with attribute like this:
<products>
<product ProductName="One" ProductCategory="Software::Utilities::Email">
<product ProductName="Two" ProductCategory="Software::Video::Editing">
<product ProductName="Three" ProductCategory="Software::Audio::Converter">
</products>
And how can I explode the "ProductCategory" attribute and separated it like this:
<products>
<product ProductName="One" ProductCategory="Software">
<product ProductName="One" ProductCategory="Utilities">
<product ProductName="One" ProductCategory="Email">
<product ProductName="Two" ProductCategory="Software">
<product ProductName="Two" ProductCategory="Video">
<product ProductName="Two" ProductCategory="Editing">
<product ProductName="Three" ProductCategory="Software">
<product ProductName="Three" ProductCategory="Audio">
<product ProductName="Three" ProductCategory="Converter">
</products>
An Example for you
<?php
$string = <<<XML
<products>
<product ProductName="One" ProductCategory="Software::Utilities::Email"></product>
<product ProductName="Two" ProductCategory="Software::Video::Editing"></product>
<product ProductName="Three" ProductCategory="Software::Audio::Converter"></product>
</products>
XML;
$xml = simplexml_load_string($string);
$obj = json_decode(json_encode($xml), true);
$new_xml = '<products>';
foreach($obj['product'] as $val){
$name = $val['#attributes']['ProductName'];
$pro = explode('::', $val['#attributes']['ProductCategory']);
foreach($pro as $k=>$v){
$new_xml .= '<product ProductName="'.$name.'" ProductCategory="'.$v.'"></product>';
}
}
$new_xml .= '</products>';
$file = fopen("test.xml","w");
fwrite($file, $new_xml);
fclose($file);
?>
You example XML is not valid XML. Make sure to close the product element nodes.
Load the source document into a DOM, create a new target DOM. Import the document element into the target (without child). This will create a copy of that node.
Iterate the product nodes and read the ProductCategory attribute, explode it into an array. Iterate the array an copy the node into the target document (for each value), change the attribute to the value.
$source = new DOMDocument();
$source->loadXml($xml);
$xpath = new DOMXPath($source);
$target = new DOMDocument();
$target->formatOutput = true;
$root = $target->appendChild($target->importNode($source->documentElement));
foreach ($xpath->evaluate('/products/product') as $node) {
$list = explode('::', $node->getAttribute('ProductCategory'));
foreach ($list as $value) {
$newNode = $root->appendChild($target->importNode($node));
$newNode->setAttribute('ProductCategory', $value);
}
}
echo $target->saveXml();
Demo: https://eval.in/209729
I'm trying to add a childnode in an XML document with PHP and got it OK so far except one thing. Can't get it formatted correct?
Here is the script:
$xmldoc = new DOMDocument();
$xml->formatOutput = true;
$xml->preserveWhiteSpace = false;
$xmldoc->loadXML('<?xml version="1.0" encoding="ISO-8859-1"?>
<data>
<udate>1347730639</udate>
<userid>3</userid>
</data>');
echo "<xmp>OLD:\n". $xmldoc->saveXML() ."</xmp>";
$root = $xmldoc->firstChild;
$newElement = $xmldoc->createElement('popup');
$root->appendChild($newElement);
$newText = $xmldoc->createTextNode("0");
$newElement->appendChild($newText);
echo "<xmp>NEW:\n". $xmldoc->saveXML() ."</xmp>";
After adding the node I get this:
<data>
<udate>1347730639</udate>
<userid>3</userid>
<popup>0</popup></data>
I want it to be like this:
<data>
<udate>1347730639</udate>
<userid>3</userid>
<popup>0</popup>
</data>
Where do I go wrong?
Please help and thanks in advance :-)
createElement will break formatOutput this is a general issue
See PHP BUG Report
formatOutput does not work with saveHTML
DOMDocument->formatOutput = true does not work
But you can have a work around by reloading and formatting it.
$xmldoc = new DOMDocument();
$xmldoc->loadXML('<?xml version="1.0" encoding="ISO-8859-1"?>
<data>
<udate>1347730639</udate>
<userid>3</userid>
</data>');
echo "<xmp>OLD:\n". $xmldoc->saveXML() ."</xmp>";
$root = $xmldoc->firstChild;
$newElement = $xmldoc->createElement('popup');
$root->appendChild($newElement);
$newText = $xmldoc->createTextNode("0");
$newElement->appendChild($newText);
$xml = new DOMDocument();
$xml->preserveWhiteSpace = false;
$xml->formatOutput = true;
$xml->loadXML( $xmldoc->saveXML());
echo "<xmp>NEW:\n". $xml->saveXML()."</xmp>";
Output
OLD:
<?xml version="1.0" encoding="ISO-8859-1"?>
<data>
<udate>1347730639</udate>
<userid>3</userid>
</data>
NEW:
<?xml version="1.0" encoding="ISO-8859-1"?>
<data>
<udate>1347730639</udate>
<userid>3</userid>
<popup>0</popup>
</data>
You might want to try removing all whitespace before and then formatting.
force it to remake the xml from scratch.
$xml->preserveWhiteSpace = false;
$xml->formatOutput = true;
this may sound pretty straight forward, but still I want to post this question in the forum. I have a xml file, which needs to be appended with data after the main element and save the xml file without overwriting the existing xml file but to append the data to already existing data and update the xml file.
For example my xml data looks something similar to this:
<maincontent>
<headercontent>
<product num="2102">
<name>MSG</name>
<category>Wellness</category>
<available content="YES"></available>
</product>
<product num="2101">
<name>YSD</name>
<category>Music</category>
<available content="NO"></available>
</product>
<product num="2100">
<name>RCS</name>
<category>Media</category>
<available content="YES"></available>
</product>
</headercontent>
</maincontent>
I want to add another product with all the info and append the newly added data at the top so that the newly added data should come after the headercontent.
Data to be added:
<product num="2103">
<name>AGB</name>
<category>Movies</category>
<available content="YES"></available>
</product>
The updated xml file should be looking like this as shown below:
<maincontent>
<headercontent>
<product num="2103">
<name>AGB</name>
<category>Movies</category>
<available content="YES"></available>
</product>
<product num="2102">
<name>MSG</name>
<category>Wellness</category>
<available content="YES"></available>
</product>
<product num="2101">
<name>YSD</name>
<category>Music</category>
<available content="NO"></available>
</product>
<product num="2100">
<name>RCS</name>
<category>Media</category>
<available content="YES"></available>
</product>
</headercontent>
</maincontent>
Any useful advice or a piece of example code would be really helpful.
Edit:
sorry guys I haven't posted any php code, my fault. Here is the code which I have been working on:
Thanks
<?php
$xmldoc = new DomDocument();
$xmldoc->formatOutput = true;
$productNum = "2103";
$name = "AGB";
$category = "Movies";
$content = "YES";
if($xml = file_get_contents('main.xml')){
$xmldoc->loadXML($xml);
$root = $xmldoc->firstChild;
$newElement = $xmldoc->createElement('product');
$root->appendChild($newElement);
$numAttribute = $xmldoc->createAttribute("num");
$numAttribute->value = $productNum;
$newElement->appendChild($numAttribute);
$nameElement = $xmldoc->createElement('name');
$root->appendChild($nameElement);
$nameText = $xmldoc->createTextNode($name);
$nameElement->appendChild($nameText);
$categoryElement = $xmldoc->createElement('category');
$root->appendChild($categoryElement);
$categoryText = $xmldoc->createTextNode($category);
$categoryElement->appendChild($categoryText);
$availableElement = $xmldoc->createElement('available');
$root->appendChild($availableElement);
$availableAttribute = $xmldoc->createAttribute("content");
$availableAttribute->value = $content;
$availableElement->appendChild($availableAttribute);
$xmldoc->save('main.xml');
}
?>
My xml file gets updated but the data is added to the firstchild and that too at the bottom, instead I want to add data after and in the beginning as shown above.
Here is my output:
<maincontent>
<headercontent>
<product num="2102">
<name>MSG</name>
<category>Wellness</category>
<available content="YES"/>
</product>
<product num="2101">
<name>YSD</name>
<category>Music</category>
<available content="NO"/>
</product>
<product num="2100">
<name>RCS</name>
<category>Media</category>
<available content="YES"/>
</product>
</headercontent>
<product num="2103"/><name>AGB</name><category>Movies</category><available content="YES"/></maincontent>
Any advice?
This will work.
<?php
$xmldoc = new DomDocument( '1.0' );
$xmldoc->preserveWhiteSpace = false;
$xmldoc->formatOutput = true;
$productNum = "2103";
$name = "AGB";
$category = "Movies";
$content = "YES";
if( $xml = file_get_contents( 'main.xml') ) {
$xmldoc->loadXML( $xml, LIBXML_NOBLANKS );
// find the headercontent tag
$root = $xmldoc->getElementsByTagName('headercontent')->item(0);
// create the <product> tag
$product = $xmldoc->createElement('product');
$numAttribute = $xmldoc->createAttribute("num");
$numAttribute->value = $productNum;
$product->appendChild($numAttribute);
// add the product tag before the first element in the <headercontent> tag
$root->insertBefore( $product, $root->firstChild );
// create other elements and add it to the <product> tag.
$nameElement = $xmldoc->createElement('name');
$product->appendChild($nameElement);
$nameText = $xmldoc->createTextNode($name);
$nameElement->appendChild($nameText);
$categoryElement = $xmldoc->createElement('category');
$product->appendChild($categoryElement);
$categoryText = $xmldoc->createTextNode($category);
$categoryElement->appendChild($categoryText);
$availableElement = $xmldoc->createElement('available');
$product->appendChild($availableElement);
$availableAttribute = $xmldoc->createAttribute("content");
$availableAttribute->value = $content;
$availableElement->appendChild($availableAttribute);
$xmldoc->save('main.xml');
}
?>
Hope this helps.
I have an xml file
<?xml version="1.0"?>
<category>
<name>SWEATERS</name>
<name>WATCHES</name>
<name>PANTS</name>
<name>test</name>
<name>1</name>
</category>
How i can remove the node <name>test</name> using xpath ,xquery and php. I used this code
$name='test;
$xmlfile="config/shop_categories.xml";
$xml = simplexml_load_file($xmlfile);
$target = $xml->xpath('/category[name="'.trim($name).'"]');
print_r($target[0]);
if($target == false)
return;
$domRef = dom_import_simplexml($target[0]); //Select position 0 in XPath array
$domRef->parentNode->removeChild($domRef);
$dom = new DOMDocument('1.0');
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->loadXML($xml->asXML());
$dom->save($xmlfile);
But it is not working.
Pretty sure this is a duplicate, but am too lazy to find it. Here you go:
$xml = <<< XML
<?xml version="1.0"?>
<category>
<name>SWEATERS</name>
<name>WATCHES</name>
<name>PANTS</name>
<name>test</name>
<name>1</name>
</category>
XML;
$dom = new DOMDocument;
$dom->loadXML($xml);
$xPath = new DOMXPath($dom);
foreach($xPath->query('//name[text() = "test"]') as $node) {
$node->parentNode->removeChild($node);
}
echo $dom->saveXML();
Output:
<?xml version="1.0"?>
<category>
<name>SWEATERS</name>
<name>WATCHES</name>
<name>PANTS</name>
<name>1</name>
</category>