Replacing innertext of XML node using PHP DOMDocument - php

I want to replace innertext of a XML node my XML file named test.xml is
<?xml version="1.0" encoding="utf-8"?>
<ads>
<loop>no</loop>
<item>
<description>Description 1</description>
</item>
<item>
<description>Text in item2</description>
</item>
<item>
<description>Let play with this XML</description>
</item>
</ads>
I want to change the value of loop and description tag both,
and it should be saved in test.xml like:
<?xml version="1.0" encoding="utf-8"?>
<ads>
<loop>yes</loop>
<item>
<description>Description Changing Here</description>
</item>
<item>
<description>Changing text in item2</description>
</item>
<item>
<description>We will play later</description>
</item>
</ads>
I tried code in PHP:
<?
$file = "test.xml";
$fp = fopen($file, "rb") or die("cannot open file");
$str = fread($fp, filesize($file));
$dom=new DOMDocument();
$dom->formatOutput = true;
$dom->preserveWhiteSpace = false;
$dom->loadXML($str) or die("Error");
//$dom->load("items.xml");
$root=$dom->documentElement; // This can differ (I am not sure, it can be only documentElement or documentElement->firstChild or only firstChild)
$loop=$root->getElementsByTagName('loop')->item(0);//->textContent;
//echo $loop;
if(trim($loop->textContent)=='no')
{
echo 'ok';
$root->getElementsByTagName('loop')->item(0)->nodeValue ='yes';
}
echo "<xmp>NEW:\n". $dom->saveXML() ."</xmp>";
?>
I tried only for loop tag.I don't know how to replace nodevalue in description tag.
When I run this page it shows output like:
ok
NEW:
<?xml version="1.0" encoding="utf-8"?>
<ads>
<loop>yes</loop>
<item>
<description>Description 1</description>
</item>
<item>
<description>Changing text in item2</description>
</item>
<item>
<description>Let play with this XML</description>
</item>
</ads>
It gives the value yes in browser but don't save it in test.xml any reason?

So, since you have created DOMDocument you can use DOMXpath. Or keep using getElementsByTagName()
You could do this (but only in that context):
$descriptions = $root->getElementsByTagName('description');
foreach($descriptions as $nodeDesciption)
{
$nodeDesciption->nodeValue ='Your custom value';
}

Related

Remove white spaces between tag values in xml with php

I been searching information how to remove white spaces between tag values leaved by a PHP code when I export it to XML, I will explain detailed, first I load and XML then I do a search on the file with xPath, then I remove some elements that do not match some brands and finally I reexport it as a new XML, the problem is that this new XML is full of white spaces leaved by the code. I tried trim it but it doesn't seems to work correctly.
Here is my code:
<?php
$sXML = simplexml_load_file('file.xml'); //First load the XML
$brands = $sXML->xPath('//brand'); //I do a search for the <brand> tag
function filter(string $input) { //Then I give it a list of variables
switch ($input) {
case 'BRAND 3':
case 'BRAND 4':
return false;
default:
return true;
}
}
array_walk($brands, function($brand) { //I remove all elements do not match my list
$content = (string) $brand;
if (filter($content)) {
$item = $brand->xPath('..')[0];
unset($item[0]);
}
});
$sXML->asXML('filtred.xml'); // And finally export a new xml
?>
This one is the original XML:
<?xml version="1.0" encoding="utf-8"?>
<products>
<item>
<reference>00001</reference>
<other_string>PRODUCT 1</other_string>
<brand>BRAND 1</brand>
</item>
<item>
<reference>00002</reference>
<other_string>PRODUCT 2</other_string>
<brand>BRAND 2</brand>
</item>
<item>
<reference>00003</reference>
<other_string>PRODUCT 3</other_string>
<brand>BRAND 3</brand>
</item>
<item>
<reference>00004</reference>
<other_string>PRODUCT 4</other_string>
<brand>BRAND 4</brand>
</item>
<item>
<reference>00005</reference>
<other_string>PRODUCT 5</other_string>
<brand>BRAND 5</brand>
</item>
</products>
And the output of the script sends this:
<?xml version="1.0" encoding="utf-8"?>
<products>
<item>
<reference>00001</reference>
<other_string>PRODUCT 1</other_string>
<brand>BRAND 1</brand>
</item>
<item>
<reference>00002</reference>
<other_string>PRODUCT 2</other_string>
<brand>BRAND 2</brand>
</item>
<item>
<reference>00005</reference>
<other_string>PRODUCT 5</other_string>
<brand>BRAND 5</brand>
</item>
</products>
As you can see on the output, there is a white space between product 2 and product 5 and that I need to remove it. Any help will be appreciate.
You can force SimpleXML to trim all whitespace when it reads the file, by passing the LIBXML_NOBLANKS option to simplexml_load_file:
$sXML = simplexml_load_file('file.xml', null, LIBXML_NOBLANKS);
Then when you call ->asXML(), all the whitespace will be removed, and you'll get XML all on one line, like this:
<?xml version="1.0" encoding="utf-8"?>
<products><item><reference>00003</reference><other_string>PRODUCT 3</other_string><brand>BRAND 3</brand></item><item><reference>00004</reference><other_string>PRODUCT 4</other_string><brand>BRAND 4</brand></item></products>
To re-generate whitespace based on the remaining structure, you'll need to use DOM rather than SimpleXML - but that's easy to do without changing any of your existing code, because dom_import_simplexml simply "rewraps" the XML without reparsing it.
Then you can use the DOMDocument formatOutput property and save() method to "pretty-print" the document:
$sXML = simplexml_load_file('file.xml', null, LIBXML_NOBLANKS);
// ...
// process $sXML as before
// ...
$domDocument = dom_import_simplexml($sXML)->ownerDocument;
$domDocument->formatOutput = true;
echo $domDocument->save('filtered.xml');
Another possibility is to use preg_replace:
// Get simpleXml as string
$xmlAsString = $yourSimpleXmlObject->asXML();
// Remove newlines
$xmlAsString = preg_replace("/\n/", "", $xmlAsString);
// Remove spaces between tags
$xmlAsString = preg_replace("/>\s*</", "><", $xmlAsString);
var_dump($xmlAsString);
Now you get your XML as string in one line (including the XML declaration).

PHP XML: Getting text of a node and its children

I know that this questions has been asked before, but I cannot make it work. I'm using simplexml and xpath in a PHP file. I need to get text from a node including the text in its child nodes. So, the results should be:
Mr.Smith bought a white convertible car.
Here is the xml:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test9.xsl"?>
<items>
<item>
<description>
<name>Mr.Smith bought a <car>white</car> <car>convertible</car> car.</name>
</description>
</item>
</items>
The php that's not working is:
$text = $xml->xpath('//items/item/description/name');
foreach($text as &$value) {
echo $value;
}
Please help!
To get the node value with all its child elements, you can use DOMDocument, with C14n():
<?php
$xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test9.xsl"?>
<items>
<item>
<description>
<name>Mr.Smith bought a <car>white</car> <car>convertible</car> car.</name>
</description>
</item>
</items>
XML;
$doc = new DOMDocument;
$doc->loadXML($xml);
$x = new DOMXpath($doc);
$text = $x->query('//items/item/description/name');
echo $text[0]->C14n(); // Mr.Smith bought a white convertible car.
Demo

Remove one tag and all of it's child nodes of a xml using php

i'm trying to remove one item from a xml with all of it's child nodes but when i excecute following php only the child nodes will be removed.
following is my php
<?php
header('Content-Type: text/xml');
$doc = new DOMDocument('1.0');
$url = '../../data/auction.xml';
$itemNo ="0";
$xml=simplexml_load_file($url);
foreach($xml->xpath('/items/item[itemNumber="'.$itemNo.'"]')as $child)
{
unset($child[0]);
//$child->parentNode->removeChild($node);
}
print $xml->asXML();
?>
the original XML
<?xml version="1.0"?>
<items>
<item>
<itemNumber>0</itemNumber>
<itemName>item1</itemName>
<category>Phones</category>
</item>
<item>
<itemNumber>2</itemNumber>
<itemName>item3</itemName>
<category>laptops</category>
</item>
</items>
Actual output
<items>
<item>
</item>
<item>
<itemNumber>2</itemNumber>
<itemName>item3</itemName>
<category>laptops</category>
</item>
</items>
Desired output
<items>
<item>
<itemNumber>2</itemNumber>
<itemName>item3</itemName>
<category>laptops</category>
</item>
</items>
Please tell me what i'm doing wrong

Parse XML with PHP

This is what my XML looks like
<?xml version="1.0" encoding="UTF-8"?>
<item>
<date>May 2013</date>
<html>http://www.link.to/html.html</html>
</item>
I do this in the PHP and it kind of works
$file = '../modules/xml/nl-archive.xml';
$xml = simplexml_load_file($file);
$string = '';
foreach($xml as $item){
$string .= '<a href="'.$item->html .'" ><li>'.$item->date .'</li></a>';
}
Just trying to get the contents of the date tag and html tag to show up for each of the item tags. Been googling and tinkering, can't get it right. What am I doing wrong?
Try changing your XML to have a root with children like:
<?xml version="1.0" encoding="UTF-8"?>
<items>
<item>
<date>May 2013</date>
<html>http://www.link.to/html.html</html>
</item>
</items>
Php is just fine as you have it.

PHP: Find XML node and insert child

I have an xml document with the following structure:
<?xml version="1.0" encoding="UTF-8"?>
<items>
<item>
<id>1</id>
<url>www.test.com</url>
</item>
<item>
<id>2</id>
<url>www.test2.com</url>
</item>
</items>
I would like to be able to search for a node value, such as the value of 1 for the id field. Then, once that node is found, select the parent node, which would be < item > and insert a new child within.
I know the concept of using dom document, but not sure how to do it in this instance.
This should be a start:
$dom = new DOMDocument;
$dom->loadXML($input);
$ids = $dom->getElementsByTagName('id');
foreach ($ids as $id) {
if ($id->nodeValue == '1') {
$child = $dom->createElement('tagname');
$child->appendChild($dom->createTextNode('some text'));
$id->parentNode->appendChild($child);
}
}
$xml = $dom->saveXML();
or something close to it.
You can do the same thing in a simpler way. Instead of looking for an <id/> node whose value is 1 then selecting its parent, you can reverse the relation and look for any node which has an <id/> child whose value is 1.
You can do that very easily in XPath, and here's how to do it in SimpleXML:
$items = simplexml_load_string(
'<?xml version="1.0" encoding="UTF-8"?>
<items>
<item>
<id>1</id>
<url>www.test.com</url>
</item>
<item>
<id>2</id>
<url>www.test2.com</url>
</item>
</items>'
);
$nodes = $items->xpath('*[id = "1"]');
$nodes[0]->addChild('new', 'value');
echo $items->asXML();

Categories