How to transform a cached XML via XSL?
I have a PHP script that caches a remote XML file. I want to XSL transform it before caching, but don't know how to do this:
<?php
// Set this to your link Id
$linkId = "0oiy8Plr697u3puyJy9VTUWfPrCEvEgJR";
// Set this to a directory that has write permissions
// for this script
$cacheDir = "temp/";
$cachetime = 15 * 60; // 15 minutes
// Do not change anything below this line
// unless you are absolutely sure
$feedUrl="http://mydomain.com/messageService/guestlinkservlet?glId=";
$cachefile = $cacheDir .$linkId.".xml";
header('Content-type: text/xml');
// Send from the cache if $cachetime is not exceeded
if (file_exists($cachefile) && (time() - $cachetime
< filemtime($cachefile)))
{
include($cachefile);
echo "<!-- Cached ".date('jS F Y H:i', filemtime($cachefile))." -->\n";
exit;
}
$contents = file_get_contents($feedUrl . $linkId);
// show the contents of the XML file
echo $contents;
// write it to the cache
$fp = fopen($cachefile, 'w');
fwrite($fp, $contents);
fclose($fp);
?>
This is the XSL string I want to use to transform it:
<xsl:template match="/">
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<xsl:apply-templates select="messageList" />
</Document>
</kml>
</xsl:template>
<xsl:template match="messageList">
<name>My Generated KML</name>
<xsl:apply-templates select="message" />
</xsl:template>
<xsl:template match="message">
<Placemark>
<name><xsl:value-of select="esnName" /></name>
<Point>
<coordinates>
<xsl:value-of select="latitude" />,<xsl:value-of select="longitude" />
&开发者_开发技巧lt;/coordinates>
</Point>
</Placemark>
</xsl:template>
I want to actually transform XML input and save/return a KML format. Can someone please help adjust this script? This was given to me and I am a little new to it.
$domOrigin = new DOMDocument('1.0');
$domOrigin->loadXML($contents);
$domXsl = new DOMDocument('1.0');
$domXsl->load('/path/to/stylesheet.xsl',LIBXML_NOCDATA);
$processor = new XSLTProcessor();
$processor->importStylesheet($domXsl);
file_put_contents($cachfile, $processor->transformToXml($domOrigin));
Ill leave it to you to integrate that :-)
Use the XSL extension, there is an example here:
http://www.php.net/manual/en/book.xsl.php#90510
replace your file_get_contents call with:
$XML = new DOMDocument();
$XML->load( $feedUrl . $linkId );
/*
this is the same as the example:
*/
$xslt = new XSLTProcessor();
$XSL = new DOMDocument();
$XSL->load( $xslFile );
$xslt->importStylesheet( $XSL );
then replace the "print" line with file_put_contents( $cachefile, $xslt->transformToXML( $XML ) );
Never use include
on anything except a local php source file. It will process the included contents as PHP source. Here is readfile()
for other content.
ext/xslt
provides an XSLT 1.0 processor with EXSLT support.
I suggest using the cache file as a fallback if here is an error fetch or transforming the external resource also.
$contents = '';
// validate cache
if (
(!$useCache) ||
(!file_exists($chacheFile)) ||
(filemtime($cacheFile) > time() - $expires)
) {
// fetch and transform xml content
$contents = fetchAndTransform($xmlFile, $xsltFile);
if ($useCache) {
// write cache file
file_put_contents($cacheFile, $contents);
}
}
// invalid cache or fetch/transform failure - read cache file
if ($useCache && !$contents) {
// read cache file
$contents = file_get_contents($cacheFile);
}
// output if here is contents
if ($contents) {
} else {
// error handling
}
function fetchAndTransform(string $xmlFile, string $xsltFile): string {
// read xml into DOM
$xmlDocument = new DOMDocument();
$xmlDocument->load($xmlFile);
// read xsl into DOM
$xslDocument = new DOMDocument();
$xslDocument->load($xsltFile);
// initialize xslt processor
$processor = new XSLTProcessor();
// import template
$processor->importStylesheet($xslDocument);
// transform
return $processor->transformToXml($xmlDocument);
}
The namespaces are applied to the nodes while parsing the XSLT (during $xslDocument->load($xsltFile)
. You need to define the KML namespace (http://www.opengis.net/kml/2.2
) on the XSL stylesheet element. So that the parser will put any element without a namespace prefix into it. Otherwise Placemark
, name
, ... will not be in the KML namespace.
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.opengis.net/kml/2.2">
<xsl:template match="/">
<kml>
<Document>
<xsl:apply-templates select="messageList" />
</Document>
</kml>
</xsl:template>
<xsl:template match="messageList">
<name>My Generated KML</name>
<xsl:apply-templates select="message" />
</xsl:template>
<xsl:template match="message">
<Placemark>
<name><xsl:value-of select="esnName" /></name>
<Point>
<coordinates>
<xsl:value-of select="latitude" />,<xsl:value-of select="longitude" />
</coordinates>
</Point>
</Placemark>
</xsl:template>
</xsl:stylesheet>
XSLT;
精彩评论