Removed ALL junk nodes in xml using php
This is the sample input for the example:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<!--comment1-->
<elem>a</elem>
<junk>b</junk>
<elem>
<!--comment2-->
<junk>c<junk>d</junk></junk>
</elem>
<!--comment3-->
<junk>e</junk>
</root>
This is the resulting XML:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<elem>a</elem>
<elem>
</elem>
</root>
I look documents and applied like this:
$doc = new DOMDocument();
$doc->loadXML($xml);
$xpath = new DOMXPath($doc);
foreach ($xpath->query('/root/') as $elem) {
$elem->parentNode->removeChild($elem);
}
for my case will remove all node "junk" and they will everywhere in xml document.
foreach ($xpath->query('//junk') as $elem)
Related
I'm tring to show some XML for Italian Electronic invoices received, using my custom stylesheet.xsl
All is ok when XML received start with:
<?xml version="1.0" encoding="UTF-8"?>
<p:FatturaElettronica xmlns:p="http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2" versione="FPR12">
but I've received some XML starting with:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="fatturapa_v1.2.xsl"?>
<p:FatturaElettronica xmlns:p="http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2" versione="FPR12">
in this case i get browser error when I try to open file because on my webapp i have not the fatturapa_v1.2.xml saved:
Error loading style sheet: XSLT style sheet interpretation failed.
Is there a way to strip out from this XML this line only, using PHP? Thanks
<?xml-stylesheet type="text/xsl" href="fatturapa_v1.2.xsl"?>
Everything in DOM is a node. In this case this is a processing instruction. You can use Xpath to find it and then remove it from its parent node:
$xml = <<<'XML'
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="fatturapa_v1.2.xsl"?>
<p:FatturaElettronica xmlns:p="http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2" versione="FPR12"/>
XML;
$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMXpath($document);
foreach ($xpath->evaluate('/processing-instruction()[name() = "xml-stylesheet"]') as $pi) {
// var_dump($pi);
$pi->parentNode->removeChild($pi);
}
echo $document->saveXML();
How to remove the leading and trailing white space between open and closing XML?
$sampleXML = '<?xml version="1.0" encoding="ISO-8859-1"?>
<note>
<PersonName>
<GivenName> David </GivenName>
<MiddleName> Raj</MiddleName>
<Affix>JR</Affix>
</PersonName>
<Aliases>
<PersonName>
<GivenName></GivenName>
<MiddleName></MiddleName>
<FamilyName></FamilyName>
</PersonName>
</Aliases>
<DemographicDetail>
<GovernmentId countryCode="US">testIDs data </GovernmentId>
<DateOfBirth>2000-12-12</DateOfBirth>
</DemographicDetail>
</note>
<anothertag>
<data type="credit">
<Vendor score="yes"> vendor name </Vendor>
</data>
</anothertag>';
$doc = new DOMDocument;
$doc->loadXML($xml);
foreach ($doc->documentElement->childNodes as $node) {
}
$xpath = new DOMXpath($doc);
$xml = $doc->saveXML($doc, LIBXML_NOEMPTYTAG);
I have tried using getElementsByTagName. But the tag name is dynamic. So it doesn't work for me in this case.
Is their any bulid in php class?
Expected XML:
<?xml version="1.0" encoding="ISO-8859-1"?>
<note>
<PersonName>
<GivenName>David</GivenName>
<MiddleName>Raj</MiddleName>
<Affix>JR</Affix>
</PersonName>
<Aliases>
<PersonName>
<GivenName></GivenName>
<MiddleName></MiddleName>
<FamilyName></FamilyName>
</PersonName>
</Aliases>
<DemographicDetail>
<GovernmentId countryCode="US">testIDs data</GovernmentId>
<DateOfBirth>2000-12-12</DateOfBirth>
</DemographicDetail>
</note>
<anothertag>
<data type="credit">
<Vendor score="yes">vendor name</Vendor>
</data>
</anothertag>
Thanks in advance.
You can traverse on all the nodes and trim the node value, for this you need a recursive function to traverse all the nodes:
function trimNodes(DOMNode $node) {
foreach ($node->childNodes as $child){
if($child->hasChildNodes()) {
trimNodes($child);
} else{
$child->nodeValue = trim($child->nodeValue);
}
}
}
call this function and send the $doc to it, then you will have your expected XML.
Please note your XML needs to have a root node. You have two root nodes currently (anothertag, note), wrap them in one root node.
If $sampleXML is just a string, then I think a regular expression could give you what you are looking for:
$pattern = '/(?<=\>)\s+(?=[a-zA-Z0-9,\.\_])|(?<=[a-zA-Z0-9,\.\_])\s+(?=\<)/';
$sampleXML = preg_replace($pattern, '', $sampleXML);
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
I am beginner in php and currently working on php-xml parsing in which i am not getting how should i append node with specific node having different value in same xml file.
Explanation :
Since i don't have enough data so i need to duplicate nodes (here it is test node) so that i can increase my file size and then work on parsing.
In short i need to generate big xml file with exisitng single node.
Current Xml File :
<?xml version="1.0" encoding="utf-8"?>
<Testings xmlns="http://rets.org/xsd/Syndication/2012-03" xmlns:Level="http://rets.org/xsd/RETSLevel" xmlns:schemaLocation="http://rets.org/xsd/Syndication/2012-03/Syndication.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="0.96" versionTimestamp="2012-02-07T03:00:00Z" xml:lang="en-us">
<Test>
<Area>
<Level:preference-order>1</Level:preference-order>
<Level:address-preference-order>1</Level:address-preference-order>
<Level:FullStreetAddress>2245 Don Knotts Blvd.</Level:FullStreetAddress>
<Level:UnitNumber>2</Level:UnitNumber>
<Level:City>Morgantown</Level:City>
<Level:StateOrProvince>WV</Level:StateOrProvince>
<Level:PostalCode>26501</Level:PostalCode>
<Level:Country>true</Level:Country>
</Area>
<AreaPrice Level:isgSecurityClass="Public">234000</ListPrice>
<AreaPriceLow Level:isgSecurityClass="Public">214000</ListPriceLow>
<AreaPrices>
<AreaPrice>
<AreaListPrice Level:currencyCode="AUS" Level:isgSecurityClass="Public">483999.0</AreaListPrice>
<AreaListPriceLow Level:currencyCode="EUR" Level:isgSecurityClass="Public">470000.0</AreaListPriceLow>
</AreaPrice>
</AreaPrices>
</Test>
</Testings>
Expected Output:
<?xml version="1.0" encoding="utf-8"?>
<Testings xmlns="http://rets.org/xsd/Syndication/2012-03" xmlns:Level="http://rets.org/xsd/RETSLevel" xmlns:schemaLocation="http://rets.org/xsd/Syndication/2012-03/Syndication.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="0.96" versionTimestamp="2012-02-07T03:00:00Z" xml:lang="en-us">
<Test>
<Area>
<Level:preference-order>1</Level:preference-order>
<Level:address-preference-order>1</Level:address-preference-order>
<Level:FullStreetAddress>2245 Don Knotts Blvd.</Level:FullStreetAddress>
<Level:UnitNumber>2</Level:UnitNumber>
<Level:City>Morgantown</Level:City>
<Level:StateOrProvince>WV</Level:StateOrProvince>
<Level:PostalCode>26501</Level:PostalCode>
<Level:Country>true</Level:Country>
</Area>
<AreaPrice Level:isgSecurityClass="Public">234000</ListPrice>
<AreaPriceLow Level:isgSecurityClass="Public">214000</ListPriceLow>
<AreaPrices>
<AreaPrice>
<AreaListPrice Level:currencyCode="AUS" Level:isgSecurityClass="Public">483999.0</AreaListPrice>
<AreaListPriceLow Level:currencyCode="EUR" Level:isgSecurityClass="Public">470000.0</AreaListPriceLow>
</AreaPrice>
</AreaPrices>
</Test>
<Test>
<Area>
<Level:preference-order>1</Level:preference-order>
<Level:address-preference-order>1</Level:address-preference-order>
<Level:FullStreetAddress>2245 Don Knotts Blvd.</Level:FullStreetAddress>
<Level:UnitNumber>2</Level:UnitNumber>
<Level:City>Morgantown</Level:City>
<Level:StateOrProvince>WV</Level:StateOrProvince>
<Level:PostalCode>26501</Level:PostalCode>
<Level:Country>true</Level:Country>
</Area>
<AreaPrice Level:isgSecurityClass="Public">15000</ListPrice>
<AreaPriceLow Level:isgSecurityClass="Public">214000</ListPriceLow>
<AreaPrices>
<AreaPrice>
<AreaListPrice Level:currencyCode="AUS" Level:isgSecurityClass="Public">483999.0</AreaListPrice>
<AreaListPriceLow Level:currencyCode="EUR" Level:isgSecurityClass="Public">470000.0</AreaListPriceLow>
</AreaPrice>
</AreaPrices>
</Test>
</Testings>
**My Approach **
$xmlString = simplexml_load_string(file_get_contents('./PhpXmlFile.xml'));
$xmlString = $xmlString->xpath('/Testings/Test/');
if ( $xmlString && is_array( $xmlString ) ) {
// since it IS an array, set to the first element of the array
$xmlString = $xmlString[0];
// And NOW we can append
$xmlString = $xmlString->addChild('Test','');
}
$dom = new DOMDocument("1.0");
$dom->preserveWhiteSpace = true;
$dom->formatOutput = true;
$dom->loadXML($xmlString->saveXML());
Thanks in advance!!
Here we are using DOMDocument for cloning a child node. Here for an example i am using nodeValue as 1000 you can change it to the value you want.
Here in a below code we are using $domDocument->getElementsByTagName("AreaPrice")->item(2)->nodeValue=1000; for item no 2 because after appending the a clone node, There will be four elements with name AreaPrice.
Try this code snippet here
<?php
ini_set('display_errors', 1);
$string = <<<HTML
<?xml version="1.0" encoding="utf-8"?>
<Testings xmlns="http://rets.org/xsd/Syndication/2012-03" xmlns:Level="http://rets.org/xsd/RETSLevel" xmlns:schemaLocation="http://rets.org/xsd/Syndication/2012-03/Syndication.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="0.96" versionTimestamp="2012-02-07T03:00:00Z" xml:lang="en-us">
<Test>
<Area>
<Level:preference-order class='sas'>1</Level:preference-order>
<Level:address-preference-order>1</Level:address-preference-order>
<Level:FullStreetAddress>2245 Don Knotts Blvd.</Level:FullStreetAddress>
<Level:UnitNumber>2</Level:UnitNumber>
<Level:City>Morgantown</Level:City>
<Level:StateOrProvince>WV</Level:StateOrProvince>
<Level:PostalCode>26501</Level:PostalCode>
<Level:Country>true</Level:Country>
</Area>
<AreaPrice Level:isgSecurityClass="Public">234000</AreaPrice>
<AreaPriceLow Level:isgSecurityClass="Public">214000</AreaPriceLow>
<AreaPrices>
<AreaPrice>
<AreaListPrice Level:currencyCode="AUS" Level:isgSecurityClass="Public">483999.0</AreaListPrice>
<AreaListPriceLow Level:currencyCode="EUR" Level:isgSecurityClass="Public">470000.0</AreaListPriceLow>
</AreaPrice>
</AreaPrices>
</Test>
</Testings>
HTML;
$domDocument = new DOMDocument();
$domDocument->loadXML($string);
$results=$domDocument->getElementsByTagName("Test");
$clonedNode=$results->item(0)->cloneNode(true);
$results->item(0)->parentNode->appendChild($clonedNode);
$domDocument->getElementsByTagName("AreaPrice")->item(2)->nodeValue=1000;//change the value you want.
echo $domDocument->saveXML();
I'm trying to add a child to an Simple XML object, but when an element with the same name already exists on that level it doesn't get added.
Here's what I'm trying:
$str = '<?xml version="1.0"?>
<root>
<items>
<item></item>
</items>
</root>';
$xml = new SimpleXMLElement($str);
$xml->addChild('items');
print $xml->asXML();
I get the exact same xml as I started with, when what I really want is a second empty items element. If I use another element name than it does get added.
Use this code for adding a new items node in your example:
$str = '<?xml version="1.0"?>
<root>
<items>
<item></item>
</items>
</root>';
$xml = new SimpleXMLElement($str);
$xml->addChild('items', '');
var_dump($xml->asXML());
Which outputs:
string '<?xml version="1.0"?>
<root>
<items>
<item/>
</items>
<items></items></root>
' (length=109)
You could use simpleloadxml as alternate
$xml = simplexml_load_file("myxml.xml");
$sxe = new SimpleXMLElement($xml->asXML());
$itemsNode = $sxe->items[0];
$itemsNode->addChild("item", $newValue);
$sxe->asXML("myxml.xml");