Remove stylesheet from XML with PHP - php

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

Related

Add xml-stylesheet tag simpleXML php

Hy guys this is my simple code:
$xml = new SimpleXMLElement('<p:FatturazioneElettronica xmlns:p="http://microsoft.com/wsdl/types/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://dummy.com"/>');
$xml->addAttribute("versione","FPR12");
$FatturaElettronicaHeader = $xml->addChild('FatturaElettronicaHeader',null,'http://dummy.com');
the xml results is:
<p:FatturazioneElettronica xmlns:p="http://microsoft.com/wsdl/types/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://dummy.com" versione="FPR12">
<FatturaElettronicaHeader>
<DatiTrasmissione>
....
How can add at the top of my xml "xml-stylesheet"?
<?xml-stylesheet type="text/xsl" href="fatturapa_v1.2.xsl" ?>
SimpleXML isn't very good at doing anything other than simple things (think that's were the name is very apt). The only way I can think of doing it is to use DOMDocument, which provides a richer API and you should be able to do it as follows...
$xmlD = new DOMDocument( "1.0", "ISO-8859-15" );
$xmlD->appendChild($xmlD->createProcessingInstruction('xml-stylesheet', 'type="text/xsl" href="fatturapa_v1.2.xsl"'));
$xmlD->appendChild($xmlD->importNode(dom_import_simplexml($xml)));
echo $xmlD->saveXML();
This creates a new DOMDocument instance and then adds a few things. First it uses createProcessingInstruction() to add the processing instruction for the style sheet. Then it imports the existing contents of your SimpleXML document (in $xml) and appends this to the end. The echo should give you a document something like...
<?xml version="1.0" encoding="ISO-8859-15"?>
<?xml-stylesheet type="text/xsl" href="fatturapa_v1.2.xsl"?>
<p:FatturazioneElettronica xmlns:p="http://microsoft.com/wsdl/types/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://dummy.com" versione="FPR12"/>

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

Append / Clone nodes in xml File with help of php

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

PHP SimpleXMLElement problems with xml node

I want to create an XML with the following structure:
<?xml version="1.0" encoding="UTF-8"?>
<content>
<!-- content goes here -->
</content>
I originally created the xml node like this:
$xml = new SimpleXMLElement('<xml/>');
$content = $xml->addChild('content');
// add data to content
but that doesn't allow for adding attributes to the xml node, so now I do this:
$xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?>'
.'<content></content>');
For some reason it doesn't work without adding the content node, but whatever, it gets the structure right.
Now, how do I assign the content node to a variable like I did above, so I can add data to it?
In your case the $xml variable is equal to the content node just try the following:
$xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?>'
.'<content></content>');
$xml->addAttribute('Attribute', 'value');
$xml->addChild('node_name', 'value');
echo $xml->asXML();
this should print
<?xml version="1.0" encoding="UTF-8"?>
<content Attribute="value"><node_name>value</node_name></content>
E.g.
<?php
$content = new SimpleXMLElement('<content />');
$content['attr']='value';
echo $content->asXML();
prints
<?xml version="1.0"?>
<content attr="value"/>
--- edit:
To keep the encoding=utf-8:
$content = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?>
<content />');
An XML document must have at least one element. That is the document element. In your question this is the content element.
You can create a SimpleXMLElement of it by just instantiating it with this minimum string:
$xml = new SimpleXMLElement('<content/>');
The variable $xml then represents that element. You can then...
... add attributes: $xml['attribute'] = 'value';
... set the content-text: $xml[0] = 'text';
... add child-elements: $xml->child = 'value';
This exemplary line-up then would have created the following XML (beautified, also: online demo):
<?xml version="1.0"?>
<content attribute="value">
text
<child>value</child>
</content>

Removed all junk nodes in xml using php?

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)

Categories