Replacing the XSLT 2.0 function iri-to-uri with a list of URI's from a parameter passed in via Java

438 views Asked by At

I have some XSL files that work through all the files in a directory recurively, basically it reads in a variable called collection:

<xsl:variable name="collection">
        <xsl:copy-of select="collection(iri-to-uri('./?select=*.xml;recurse=yes'))/*"/>
    </xsl:variable>

and then later on, we have something like:

<xsl:for-each-group     select="$collection/configuration/services/service" group-by="serviceKey" >

This was fine for a while but now I want to pass in alist of files that would make up the variable collection. Im working with java so I caneffectively pass in a comma delimined list of files paths or URI's, but I'm not sure how to handle that in the XSL file, so that it populates the collection variable like the recursive iri-to-uri function was working.

2

There are 2 answers

1
Michael Kay On BEST ANSWER

Another solution would be to implement a CollectionURIResolver in your Java application. You can nominate this to Saxon before running your transformation. When you call the collection() function, Saxon will call your CollectionURIResolver, which can pass back a list of documents or URIs.

http://www.saxonica.com/documentation/index.html#!javadoc/net.sf.saxon.lib/CollectionURIResolver

6
Florent Georges On

If you want to pass a list of documents from your environment to the stylesheet, use a sequence of document nodes:

<xsl:param name="docs" as="document-node()+"/>

If you prefer passing only their URIs, then use a sequence of strings (or maybe of xs:anyURI):

<xsl:param name="uris" as="xs:string+"/>
<xsl:param name="docs" select="$uris ! doc(.)"/>

If you want to pass a list of collection URIs, like the one you use in your example, giving a directory and a filename pattern (this is the Saxon way to resolve collection URIs), then use the following instead:

<xsl:param name="uris" as="xs:string+"/>
<xsl:param name="docs" select="$uris ! collection(.)"/>

Note that in the 2 last code snippets above, having $docs defined as a parameter, with a default value depending on another parameter, enable the user to pass either the value of docs directly (a sequence of document nodes), or to pass their URIs instead (you have to change xs:string+ to xs:string* though, if you want to accept an empty sequence for it).

If you want the environment to be able to pass document nodes, document URIs and collection URIs, and combine them, then:

<xsl:param name="uris"  as="xs:string*"/>
<xsl:param name="colls" as="xs:string*"/>
<xsl:param name="docs"  as="document-node()*"/>

<xsl:variable name="my-docs" select="
   $uris ! doc(.), $colls ! collection(.), $docs"/>

PS: You do not need iri-to-uri() in your example.

PS II: Note that the operator ! is 3.0. If you cannot use it, use for $uri in $uris return doc($uri) instead of $uris ! doc(.).