Search code examples
xmlsvgxsltsaxon

Getting the filename during collection processing in Saxon XSLT


I'm trying to process a directory full of SVG files using XSL-T. I currently have tried:

<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
                xmlns="http://www.w3.org/2000/svg"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xpath-default-namespace="http://www.w3.org/2000/svg"
                exclude-result-prefixes="xsl">
  <xsl:output method="xml" doctype-public="-//W3C//DTD SVG 1.1//EN http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"/>
  <xsl:strip-space elements="*"/>

  <xsl:template name="main">
    <svg xmlns="http://www.w3.org/2000/svg">
      <defs/>
      <xsl:apply-templates select="collection(concat(resolve-uri('src/images'),'?select=*.svg;content-type=application/xml'))"/>
    </svg>
  </xsl:template>

  <xsl:template match="/">
    <xsl:apply-templates select="svg"/>
  </xsl:template>

  <xsl:template match="svg">
    <xsl:element name="symbol">
      <xsl:attribute name="id"><xsl:value-of select="tokenize(document-uri(/),'/')[last()]"/></xsl:attribute>
      <xsl:attribute name="viewBox"><xsl:value-of select="@viewBox"/></xsl:attribute>
      <xsl:apply-templates select="path"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="path">
    <xsl:element name="path">
      <xsl:apply-templates select="@d,@fill"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="@d">
    <xsl:attribute name="d"><xsl:value-of select="."/></xsl:attribute>
  </xsl:template>

  <xsl:template match="@fill">
    <xsl:attribute name="fill"><xsl:value-of select="."/></xsl:attribute>
  </xsl:template>

</xsl:stylesheet>

Using this from the command line: java net.sf.saxon.Transform -it:main -xsl:"%XSL%\svg-sprite.xsl" -o:"%OUT%\sprite.svg"

It's sooooo close to working, but I need to get the filename of the included SVG file to use as the id attribute on the <symbol> element.

I've tried several constructions, using <xsl:for-each instead of the <xsl:apply-templates and everything else I could think of, but I just can't get it to access the filename. Any help would be greatly appreciated.


Solution

  • I assume your attempt with document-uri fails, that is by now a known issue in Saxon as various requirements of the specs made Saxonica change its implementation; there is an issue in the ongoing XPath 4 work to relax the requirements so that document-uri's functionality can be restored.

    But in most uses cases base-uri will do so try that.

    As an alternative you can start with uri-collection instead of collection, then you directly have the URI of each collection of which you can easily extract the file name, and process the document using doc($uri) with e.g. apply-templates.