开发者

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;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜