I have an XSLT file where I want to utilize a function in the http://exslt.org/strings
namespace. My code below fails whenever the str:tokenize
function gets called.
I'm currently using XslCompiledTransform as my processor in .NET 6.0. The error that I get back from that is as follows:
Error: Cannot find a script or an extension object associated with namespace 'exslt.org/strings'.
This is my XSLT file:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
version="1.0"
xmlns:str="http://exslt.org/strings"
xmlns:kml="http://www.opengis.net/kml/2.2"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="str kml fn xsl">
<xsl:output indent="yes"/>
<xsl:strip-space elements="kml:coordinates" />
<xsl:template match="kml:kml">
<nvg version="1.4.0">
<xsl:apply-templates select="kml:Document"/>
</nvg>
</xsl:template>
<xsl:template match="kml:Document">
<g>
<xsl:copy-of select="@id"/>
<xsl:attribute name="label">
<xsl:value-of select="kml:name"/>
</xsl:attribute>
<xsl:apply-templates select="kml:Folder"/>
<xsl:apply-templates select="kml:Placemark"/>
</g>
</xsl:template>
<xsl:template match="kml:Folder">
<g>
<xsl:copy-of select="@id"/>
<xsl:attribute name="label">
<xsl:value-of select="kml:name"/>
</xsl:attribute>
<xsl:apply-templates select="kml:Folder"/>
<xsl:apply-templates select="kml:Placemark"/>
</g>
</xsl:template>
<xsl:template match="kml:Placemark">
<xsl:apply-templates select="kml:Point"/>
<xsl:apply-templates select="kml:LineString"/>
<xsl:apply-templates select="kml:LinearRing"/>
<xsl:apply-templates select="kml:Polygon"/>
<xsl:apply-templates select="kml:MultiGeometry"/>
</xsl:template>
<xsl:template match="kml:MultiGeometry">
<composite>
<xsl:apply-templates select="kml:Point"/>
<xsl:apply-templates select="kml:LineString"/>
<xsl:apply-templates select="kml:LinearRing"/>
<xsl:apply-templates select="kml:Polygon"/>
</composite>
</xsl:template>
<xsl:template match="kml:Point">
<point>
<xsl:copy-of select="@id"/>
<xsl:attribute name="x">
<xsl:value-of select="str:tokenize(kml:coordinates, ',')[1]"/>
</xsl:attribute>
<xsl:attribute name="y">
<xsl:value-of select="str:tokenize(kml:coordinates, ',')[2]"/>
</xsl:attribute>
<xsl:attribute name="label">
<xsl:value-of select="(../../kml:name | ../kml:name)[last()]"/>
</xsl:attribute>
</point>
</xsl:template>
<xsl:template match="kml:LineString">
<polyline>
<xsl:copy-of select="@id"/>
<xsl:attribute name="points">
<xsl:for-each select="str:tokenize(translate(kml:coordinates, ' 	 ', ' '), ' ')">
<xsl:value-of select="str:tokenize(string(.), ',')[1]"/>,<xsl:value-of select="str:tokenize(string(.), ',')[2]"/><xsl:value-of select="string(' ')"/>
</xsl:for-each>
</xsl:attribute>
<xsl:attribute name="label">
<xsl:value-of select="(../../kml:name | ../kml:name)[last()]"/>
</xsl:attribute>
</polyline>
</xsl:template>
<xsl:template match="kml:LinearRing">
<polygon>
<xsl:copy-of select="@id"/>
<xsl:attribute name="points">
<xsl:for-each select="str:tokenize(translate(kml:coordinates, ' 	 ', ' '), ' ')">
<xsl:value-of select="str:tokenize(string(.), ',')[1]"/>,<xsl:value-of select="str:tokenize(string(.), ',')[2]"/><xsl:value-of select="string(' ')"/>
</xsl:for-each>
</xsl:attribute>
<xsl:attribute name="label">
<xsl:value-of select="(../../kml:name | ../kml:name)[last()]"/>
</xsl:attribute>
</polygon>
</xsl:template>
<xsl:template match="kml:Polygon">
<xsl:if test="kml:innerBoundaryIs">
<composite>
<polygon>
<xsl:copy-of select="@id"/>
<xsl:attribute name="points">
<xsl:for-each select="str:tokenize(translate(kml:outerBoundaryIs/kml:LinearRing/kml:coordinates, ' 	 ', ' '), ' ')">
<xsl:value-of select="str:tokenize(string(.), ',')[1]"/>,<xsl:value-of select="str:tokenize(string(.), ',')[2]"/><xsl:value-of select="string(' ')"/>
</xsl:for-each>
</xsl:attribute>
<xsl:attribute name="label">
<xsl:value-of select="(../../kml:name | ../kml:name)[last()]"/>
</xsl:attribute>
</polygon>
<xsl:for-each select="kml:innerBoundaryIs/kml:LinearRing">
<polygon label="Hole">
<xsl:attribute name="points">
<xsl:for-each select="str:tokenize(translate(kml:coordinates, ' 	 ', ' '), ' ')">
<xsl:value-of select="str:tokenize(string(.), ',')[1]"/>,<xsl:value-of select="str:tokenize(string(.), ',')[2]"/><xsl:value-of select="string(' ')"/>
</xsl:for-each>
</xsl:attribute>
</polygon>
</xsl:for-each>
</composite>
</xsl:if>
<xsl:if test="not(kml:innerBoundaryIs)">
<polygon>
<xsl:copy-of select="@id"/>
<xsl:attribute name="points">
<xsl:for-each select="str:tokenize(translate(kml:outerBoundaryIs/kml:LinearRing/kml:coordinates, ' 	 ', ' '), ' ')">
<xsl:value-of select="str:tokenize(string(.), ',')[1]"/>,<xsl:value-of select="str:tokenize(string(.), ',')[2]"/><xsl:value-of select="string(' ')"/>
</xsl:for-each>
</xsl:attribute>
<xsl:attribute name="label">
<xsl:value-of select="(../../kml:name | ../kml:name)[last()]"/>
</xsl:attribute>
</polygon>
<xsl:for-each select="kml:innerBoundaryIs/kml:LinearRing">
<polygon label="Hole">
<xsl:attribute name="points">
<xsl:for-each select="str:tokenize(translate(kml:coordinates, ' 	 ', ' '), ' ')">
<xsl:value-of select="str:tokenize(string(.), ',')[1]"/>,<xsl:value-of select="str:tokenize(string(.), ',')[2]"/><xsl:value-of select="string(' ')"/>
</xsl:for-each>
</xsl:attribute>
</polygon>
</xsl:for-each>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
This file to convert KML to a vector graphic has been given to me by someone who was given it by someone who was given it so basically everything has been lost in translation.
Any help would be very valuable if possible.
Thanks
The specification of EXSLT has moved to http://exslt.github.io
However, the reason your code is failing is not because the specification has moved, it's because the functions you want are not implemented (or configured) in your chosen XSLT processor.
These days you'll probably find it easy enough to find a processor that implements XSLT 2.0, which has a
tokenize
function in the standard function namespace. EXSLT was basically a stop-gap solution until XSLT 2.0 was standardised, which happened in 2007.