I have an xml document which I transform, view in the browser and save to a directory.
I would like to add a linked stylesheet to the saved version of the file. I've tried str_replace as below (might be incorrect usage) and also using xsl processing instruction.
xsl processing instruction worked to a degree, if you view source in the browser, you would see the stylesheet link, however it would not save this information to the saved file!!
All I want to do is take the raw xml file, transform it with the stylesheet, save it to a directory and append the xsl stylesheet to the header of the new file, so when the newly saved xml file is opened in the browser, the stylesheet is applied automatically. Hope this makes sense!!
My code is below.
//write to the file
$id = $_POST['id'];//xml id
$path = 'xml/';//send to xml directory
$filename = $path. $id . ".xml";
$header = str_replace('<?xml version="1.0" encoding="UTF-8"?>', '<?xml version="1.0" encoding="UTF-8" ?><?xml-stylesheet type="text/xsl" href="../foo.xsl"?>');
$article->asXML($filename);//saving the original xml as new file with posted id
$xml = new DOMDocument;
$xml->load($filename);
$xsl = new DOMDocument;
$xsl->load('insert.xsl');
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
echo $proc->transformToXML($xml);
Thanks in advance!
You could use the <xsl:processing-instruction/> tag in the XSLT-file to add the stylesheet link.
<xsl:processing-instruction name="xml-stylesheet">
type="text/xsl" href="../foo.xsl"
</xsl:processing-instruction>
This would produce:
<?xml-stylesheet type="text/xsl" href="../foo.xsl"?>
Alternativly, you could do it with a DOMDocument.
$newXml = $proc->transformToXML($xml);
// Re-create the DOMDocument with the new XML
$xml = new DOMDocument;
$xml->loadXML($newXml);
// Find insertion-point
$insertBefore = $xml->firstChild;
foreach($xml->childNodes as $node)
{
if ($node->nodeType == XML_ELEMENT_NODE)
{
$inertBefore = $node;
break;
}
}
// Create and insert the processing instruction
$pi = $xml->createProcessingInstruction('xml-stylesheet', 'type="text/xsl" href="../foo.xsl"');
$xml->insertBefore($pi, $insertBefore);
echo $xml->saveXML();
Related
How to create a valid XML tree using only PHP?
I have been running into many troubles with creating an XML tree just using PHP. I already have some code to show where I am at right now:
$xml = new DOMDocument("1.0");
$verb = $xml->createElement ('verb');
$vtext = $xml->createTextNode($_POST['verb']);
$verb->appendChild($vtext);
$xml->appendChild ($verb);
$adverb = $xml->createElement ('adverb');
$advtext = $xml->createTextNode($_POST['adverb']);
$adverb->appendChild($advtext);
$xml->appendChild ($adverb);
$xml ->save("'".$_POST[verb]."'.xml") or die ("error creating file");
So, with this and the user input, it creates a file that is whatever the verb is. The only thing is, I keep getting error messages that there is extra content below the verbs.
I know that this is because I'm not adding a root element, but how exactly would you add this root element without creating errors? There are very little forums even talking about PHP and XML alone, so it's hard to find one that's about making an XML tree.
How about something like this?
$xml = new DOMDocument("1.0");
$root = $xml->createElement ('root');
$xml->appendChild($root);
$verb = $xml->createElement ('verb');
$vtext = $xml->createTextNode($_POST['verb']);
$verb->appendChild($vtext);
$root->appendChild ($verb);
$adverb = $xml->createElement ('adverb');
$advtext = $xml->createTextNode($_POST['adverb']);
$adverb->appendChild($advtext);
$root->appendChild ($adverb);
$xml ->save("'".$_POST[verb]."'.xml") or die ("error creating file");
This is a sample i have found in stackoverflow and this work for me! hope this will also help you!
<?php
/* create a dom document with encoding utf8 */
$domtree = new DOMDocument('1.0', 'UTF-8');
/* create the root element of the xml tree */
$xmlRoot = $domtree->createElement("xml");
/* append it to the document created */
$xmlRoot = $domtree->appendChild($xmlRoot);
$currentTrack = $domtree->createElement("track");
$currentTrack = $xmlRoot->appendChild($currentTrack);
/* you should enclose the following two lines in a cicle */
$currentTrack->appendChild($domtree->createElement('path','song1.mp3'));
$currentTrack->appendChild($domtree->createElement('title','title of song1.mp3'));
$currentTrack->appendChild($domtree->createElement('path','song2.mp3'));
$currentTrack->appendChild($domtree->createElement('title','title of song2.mp3'));
/* get the xml printed */
echo $domtree->saveXML();
?>
How exactly would you add this root element without creating errors?
For a DOMDocument (in general, not only for the PHP extension), the documentElement (often also called root element) is technically a child-node of the DOMDocument object.
You create it by appending it (as you already do (!)):
$xml = new DOMDocument("1.0");
$root = $xml->createElement ('root');
$xml->appendChild($root);
The new documentElement now is available as:
$xml->documentElement;
Try it your own (online Demo):
$xml = new DOMDocument("1.0");
$xml->save('php://output'); // document is empty
The output is just the XML declaration, no root element:
Then adding the root element (here named root):
$root = $xml->createElement ('root');
$xml->appendChild($root);
$xml->save('php://output'); // document has root-node now
And the Document has a Root-Node now as the output shows:
<?xml version="1.0"?>
<root/>
The $root is the documentElement now and Children can be appended to it:
$root->appendChild($xml->createTextNode("\n "));
$root->appendChild($xml->createElement('hello', 'world'));
$root->appendChild($xml->createTextNode("\n "));
$root->appendChild($xml->createElement('answer', '42'));
$root->appendChild($xml->createTextNode("\n "));
$root->appendChild($xml->createElement('danger', 'danger'));
$root->appendChild($xml->createTextNode("\n"));
$xml->save('php://output');
The output then is:
<?xml version="1.0"?>
<root>
<hello>world</hello>
<answer>42</answer>
<danger>danger</danger>
</root>
I am doing an assignment for class where I have to use a Java Servlet running on Tomcat and have it message a php file to scrape IMDB for movie information and return it as XML to the servlet. It seems to not want to accept any encoding I give it as I continuously get XML tags such as the ones below.
<result cover="url" title="Pokémon" year="1998 TV Series" director="N/A" rating="7.8" details="http://www.imdb.com/title/tt0176385/"/>
Where title of Pokemon should have an accent over the e («é»). I have the following php code to generate the xml. (Important parts only)
<?php header("Content-Type: text/xml; charset=utf-8");
$xml = new DOMDocument();
$rsp = $xml->appendChild($xml->createElement("rsp"));
$xml->encoding = 'utf-8';
$titleNames[$i] = utf8_encode($title_tmp[1]);
$results = $rsp->appendChild($xml->createElement("results"));
$results->setAttribute("total", $tableRows);
$item->setAttribute("title", $titleNames[$i]);
echo $xml->saveXML();
?>
Any help would be greatly appreciated in figuring out how to correctly display special characters!
It's impossible to say what's wrong from your code fragments (which don't even run) but $xml->encoding = 'utf-8' should work. Please compare:
$xml = new DOMDocument();
$rsp = $xml->appendChild($xml->createElement("rsp"));
$rsp->setAttribute("title", 'Pokémon');
echo $xml->saveXML();
/*
<?xml version="1.0"?>
<rsp title="Pokémon"/>
*/
... with:
$xml = new DOMDocument();
$xml->encoding = 'utf-8';
$rsp = $xml->appendChild($xml->createElement("rsp"));
$rsp->setAttribute("title", 'Pokémon');
echo $xml->saveXML();
/*
<?xml version="1.0" encoding="utf-8"?>
<rsp title="Pokémon"/>
*/
(These snippets are expected to be saved as UTF-8).
I am using XPath to query an xml document and then copy found nodes to a separate results xml file, however the problem I am having is that the XML declaration at the top gets added each time a new node is added to the results file.
Here is my php code:
$allEventsForVenue = $xPath->query(
"/Ticket/EventsPoints/Event[contains(PerformanceName,'$searchParam')]"
);
foreach ($allEventsForVenue as $event) {
$dstDom = new DOMDocument('1.0', 'utf-8');
$dstDom->appendChild($dstDom->createElement('EventsPoints'));
$dstDom->documentElement->appendChild($dstDom->importNode($event, true));
//echo $dstDom->saveXml();
$dstDom->formatOutput = true;
$strxml .= $dstDom->saveXML();
$handle = fopen("/var/www/html/xml/searchresults$searchID.xml", "w");
fwrite($handle, $strxml);
fclose($handle);
}
Invalid XML File (two xml declarations in the one file):
->> <?xml version="1.0" encoding="utf-8"?>
<EventsPoints>
<Event ID="17">
<PerformanceName>Bressie</PerformanceName>
<PresaleTime/>
<PriceRange>17 - 17</PriceRange>
<VenueID ID="19"/>
</Event>
</EventsPoints>
->> <?xml version="1.0" encoding="utf-8"?>
<EventsPoints>
<Event ID="180">
<PerformanceName>U2</PerformanceName>
<PriceRange>20 - 20</PriceRange>
<VenueID ID="198"/>
</Event>
</EventsPoints>
You are creating new DOMDocument instance in loop. Also you are writing in each iteration. This is making new XML document on each iteration and its get appended in your xml file. What you need to do is, loop the XML generation part. Not the whole thing.
If you loop only the appendChild parts, your problem will be solved.
$dstDom = new DOMDocument('1.0', 'utf-8');
$dstDom->formatOutput = true;
foreach ($allEventsForVenue as $event) {
$dstDom->appendChild($dstDom->createElement('EventsPoints'));
$dstDom->documentElement->appendChild($dstDom->importNode($event, true));
}
file_put_contents("/var/www/html/xml/searchresults$searchID.xml", $dstDom->saveXML());
DomDocument lets you output a specific node without the xml declaration.
Just include a node in saveXML, like saveXML($node), with node being an XMLNode type object.
With this method I think you can bypass the whole "create sub-xmldocument/import node" thing, by outputting directly the desired node in a string.
use something like this
enter <?php
// Continued from example XML above.
/* Search for <a><b><c> */
$result = $xml->xpath('/a/b/c');
while(list( , $node) = each($result)) {
echo $node->asXML();
}
?>
I have a problem with php,
If I implement this code below then nothing will be happen.
$filename = "/opt/olat/olatdata/bcroot/course/85235053647606/runstructure.xml";
if (file_exists($filename)) {
$xml = simplexml_load_file($filename, 'SimpleXMLElement', LIBXML_NOCDATA);
// $xpath = new DOMXPath($filename);
}
$doc = new DOMDocument();
$doc->loadXML($xml);
$xpath = new DOMXpath($doc);
$res = $xpath->query('/org.olat.course.Structure/rootNode/children/org.olat.course.nodes.STCourseNode/shortTitle');
foreach ($res as $entry) {
echo "{$entry->nodeValue}<br/>";
}
If I change the contents of $xml in the content with the content of the $filename
$xml = '<org.olat.course.Structure><rootNode class="org.olat.course.nodes.STCourseNode"> ... ';
then it works, so i think that there is something wrong with loading methode of the xml file,
I've also tried to load the xml file as a Domdocument but it won't work neither.
And in both cases, it does work if I collect xml data via xml
for example this works
echo $Course_name = $xml->rootNode->longTitle;
loadXML takes a string as input, not the return value of simplexml_load_file. Just use file_get_contents to get the (full) contents of a file as string
Here is what i have as best i can figure what needs to be done. But im just at a loss as to how to get it to work.
Both $xml and $xmlfile are DOM objects/XML. $xml is the source of the data i want to append into $mxlfile.
$xml is sent in to the function from another function as a dom object.
This is how the xml comes to me.
<?xml version="1.0" encoding="utf-8"?>
<!-- Automatically generated data from EVE-Central.com -->
<!-- This is the new API :-) -->
<evec_api version="2.0" method="marketstat_xml">
<marketstat>
<type id="18">
<all>
<volume>1934078988.00</volume>
<avg>98.31</avg>
<max>26721.00</max>
<min>0.53</min>
<stddev>1339.78</stddev>
<median>26.31</median>
<percentile>0.00</percentile>
</all>
<buy>
<volume>1894081100.00</volume>
<avg>20.77</avg>
<max>31.31</max>
<min>0.53</min>
<stddev>7.25</stddev>
<median>26.00</median>
<percentile>28.17</percentile>
</buy>
<sell>
<volume>39997888.00</volume>
<avg>34.32</avg>
<max>26721.00</max>
<min>4.01</min>
<stddev>2339.28</stddev>
<median>29.80</median>
<percentile>26.76</percentile>
</sell>
</type>
<type id="ectera">
</type>
</marketstat>
</evec_api>
And here the part of my function i just cant get working.
$xml->preserveWhiteSpace = FALSE;
$xml->formatOutput = TRUE;
if(is_file($file)){
$xmlfile = new DOMDocument;
$xmlfile->load($file);
$dst = $xmlfile->getElementsByTagName('marketStat');
foreach($xml->getElementsByTagName('type') as $child){
$dst->appendChild($xmlfile->importNode($child));}
$xmlfile->save($file);
}
I know there's something wrong, but im just teaching myself xml and dom, so help would be much appreciated.
<?php
if(is_file($file))
{
$xmlfile = new DOMDocument;
$xml->preserveWhiteSpace = FALSE;
$xml->formatOutput = TRUE;
$xmlfile->load($file);
$dst = $xmlfile->getElementsByTagName('marketStat');
$parentLength = $dst->length;
for($i=0; $i< $parentLength ; $i++)
{
foreach($xmlfile->getElementsByTagName('type') as $child)
{
$dst->item($i)->appendChild($child);
}
}
$xmlfile->save($file);
}
Your code has two mistakes
You can set options for DOM parser after you create the document.
You can not use appendChild on list of DOM object. You have to add them on indivisual DOM element one by one.