loading XML string into Xslt sheet - php

I am trying to load a xml document I created using PHP and DOM into a xslt sheet, but having no luck.
$xml_string = $doc->saveXML();
//echo $xml_string;
$xml = new DOMDocument;
$xml->load($xml_string);
$xsl = new DOMDocument;
$xsl->load('musicInformation.xslt');
// Configure the transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl); // attach the xsl rules
echo $proc->transformToXML($xml);
I created a xml file based off some data extracted from a database and instead of saving it as an actual document I saved it as a string, I put the string into the xslt sheet and this error occurred
Warning: I/O warning : failed to load
external entity Warning: xpath.c:11079
Internal error: document without root
in
/home/dd615/public_html/webservice.php
on line 73
Any help would be much appreciated.

A string is not XML.
Valid XML needs a root element (that is, a single element that wraps all other elements in the document, apart from the XML declaration).
Such as this:
<?xml version="1.0" ?>
<root>
<element></element>
<element></element>
...
</root>
If you have multiple such roots, the XML is not valid and will fail to load.

Related

DOMDocument - get node XML without adding namespaces

Test XML:
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<testroot xmlns:abc="http://abc">
<testA>testNodeText</testA>
</testroot>
Test code:
$xml = file_get_contents('test.xml');
$dom = new \DOMDocument();
$dom->loadXML($xml);
var_dump(
$dom->C14N(),
$dom->getElementsByTagName('testA')->item(0)->C14N()
);
Result:
// 1
<testroot xmlns:abc="http://abc">\n
<testA>testNodeText</testA>\n
</testroot>
// 2
<testA xmlns:abc="http://abc">testNodeText</testA>
When getting content of node DOMDocument is adding namespace. Problem is that testA node is not equal to same testA node. This has huge impact when creating hash value from parts of XML.
I just can't get node from XML and calculate hash from it, because there are namespaces moved from document root.
Any ideas how I can get node content from DOMDocument to get it as it is in original document?

Delete node from XML file while reading it with XmlReader?

I have a script that reads XML node by node using XMLReader:
$z = new XMLReader;
$z->open('xmlfile.xml');
$doc = new DOMDocument;
while ($z->read() && $z->name !== 'item');
while ($z->name === 'item')
{
$node = simplexml_import_dom($doc->importNode($z->expand(), true));
//I read the node here
print_r($node);
//Here I want to delete it
//////////////////////////
//move to next node
$z->next('item');
}
I want to delete the node from XML file after reading it to avoid reading same data multiple times when calling the script again. What is the best way to do it? Am I able to do it while reading the file?
I couldn't find the answer anywhere else.
XMLReader has a partner called XMLWriter. So for large XML files you read the XML file using XMLReader while writing the filtered/modified data using XMLWriter into a new file.
Expanding a part of the file into DOM allows easier reading and modifications of this part but you will need to use XMLWriter to serialize the XML structure into the new file.
I implemented features (including a collapse() method) for that into FluentDOM. Here is an usage example:
$xml = <<<'XML'
<persons>
<person><name>Alice</name></person>
<person><name>Bob</name></person>
<person><name>Charlie</name></person>
</persons>
XML;
// Create the target writer and add the root element
$writer = new \FluentDOM\XMLWriter();
$writer->openUri('php://stdout');
$writer->setIndent(2);
$writer->startDocument();
$writer->startElement('persons');
// load the source into a reader
$reader = new \FluentDOM\XMLReader();
$reader->open('data://text/plain;base64,'.base64_encode($xml));
// iterate the person elements - the iterator expands them into a DOM element node
foreach (new \FluentDOM\XMLReader\SiblingIterator($reader, 'person') as $person) {
/** #var \FluentDOM\DOM\Element $person */
// ignore "Bob"
if ($person('string(name)') !== 'Bob') {
// write expanded node to the output
$writer->collapse($person);
}
}
$writer->endElement();
$writer->endDocument();
Output:
<?xml version="1.0"?>
<persons>
<person>
<name>Alice</name>
</person>
<person>
<name>Charlie</name>
</person>
</persons>
You can't edit the document while reading it .. at least not without a lot of messy inefficient code.
Best approach would be:
1) Read the entire document into a second DOMDocument object.
2) As you read nodes one by one from your XMLReader input stream, find the corresponding nodes in the DOMDocument and remove them after you are done. Be careful not to delete nodes that have children you have not yet reviewed.
3) When done save the new DomDocument to a new file name and use this as your input source for next edit session.
You will be an expert on DomDocument manipulation when you are done.
Post a new question if you run into problems.

Need to know how to process 1 XML file with 2 XSL files using PHP SimpleXML

I am very new to XSL. I need to process the same XML file with 2 XSL files using PHP SimpleXML. I have tried a few different approaches with no luck.
$xmlfile = 'media/xml_files/article.xml';
if (file_exists($xmlfile)) {
$xml = simplexml_load_file($xmlfile) or die("Error: Cannot create object");}
$xslfile = media/xsl_files/jats-html.xsl;
$xsl = simplexml_load_file($xslfile);
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
echo $proc->transformToXML($xml);
I need to process the XML with jats-PMCcit.xsl before it goes through the jats-html.xsl transform. Can somebody please point me in the right direction? I can't seem to find an answer online anywhere.
You can try using XSLTProcessor::transformToDoc() to process the first transformation and get intermediate transformation result in a DOMDocument object type. Then you can pass the DOMDocument object to transformToXML() to get the final transformation result.

PHP transform xml string to XSLT

I'm trying to run an xslt script over a xml response. But I'm having problems getting PHP/XSLT to understand the response. My PHP looks like this, the $data variable contains the XML
$movies = new SimpleXMLElement($data);
// Load the XML source
$xml = new DOMDocument;
$xml->load($movies);
$xsl = new DOMDocument;
$xsl->load('/var/www/html/app/views/xslt/rdf.xsl');
// Configure the transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl); // attach the xsl rules
$res = $proc->transformToXML($xml);
I'm getting
production.ERROR: exception 'ErrorException' with message 'DOMDocument::load(): I/O warning : failed to load external entity "/var/www/public/
"'
as my error. I've tried using simplexml_load_file and simplexml_load_string but have similar results.

How can I load multiple XML documents inside my PHP, DOM script?

I have two different XML structured documents, an XSLT that renames the elements and nodes of them to satisfy both and a PHP code that will save them into a new XML doc.
This is the code I used for testing purposes, however how can I load two or more paths like book1.xml and book2.xml into the $xml ? I know how to $dom->load( 'book1.xml' );
<?php
// create an XSLT processor and load the stylesheet as a DOM
$xproc = new XsltProcessor();
$xslt = new DomDocument;
$xslt->load('stylesheet.xslt'); // this contains the code from above
$xproc->importStylesheet($xslt);
// your DOM or the source XML (copied from your question)
$xml = '';
$dom = new DomDocument;
$dom->loadXML($xml);
?>
Read about and use the standard XSLT function document().
In XSLT 2.0 there is also standard support for producing multiple result documents -- read about the <xsl:result-document> element.
If you are bound to XSLT 1.0, you cannot produce more than one result document in one transformation. You can either use extension libraries (EXSLT, the <exsl:document> extension element) or you can produce all results in one result document and then produce every single result out of it using another transformation, that you run once for producing each result.

Categories