Subject: Re: [xsl] Act as xsl:next-match in XSLT 1 with xsl:apply-imports (not possible?)|
From: "Andrew Welch" <andrew.j.welch@xxxxxxxxx>
Date: Fri, 23 Mar 2007 14:07:43 +0000
Yesterday I tried for several hours a document-creation technique that eventually did not work. I am trying to find a solution that can be done in a one-pass with XSLT 1.0. If not possible, well, then it'd need be a two-pass transform... I hope I am just missing something here and that it's easy after all.
The problem is this: I have 30 or so small XML result documents, each expressed in its own cozy little stylesheet, and I need them combined. To do so, I hoped to use xsl:import and xsl:apply-imports and one main stylesheet where I have a list of all these inclusions. Like this:
<!-- main stylesheet --> <xsl:stylesheet ...> <xsl:import href="a.xslt" /> <xsl:import href="b.xslt" />
<xsl:template match="/"> <all-snippets> <xsl:apply-imports /> </all-snippets> </xsl:template>
<xsl:template match="text()" /> </xsl:stylesheet>
<!-- stylesheet a.xslt --> <xsl:stylesheet ...> <xsl:template match="/"> <a>We're in A hurray!</a> <xsl:apply-imports /> </xsl:template> </xsl:stylesheet>
<!-- stylesheet b.xslt --> <xsl:stylesheet ...> <xsl:template match="/"> <b>We're in B hurray!</b> <xsl:apply-imports /> </xsl:template> </xsl:stylesheet>
The output expected is: <all-snippets> <a>We're in A hurray!</a> <b>We're in B hurray!</b> </all-snippets>
But instead I got:
<all-snippets> <b>We're in B hurray!</b> </all-snippets>
The reason is obvious: the XSLT 1.0 spec mandates that when two imports are of equal import precedence (i.e., in the same file) then template matches that appear lowest in the importing file take precedence and the rest is discarded. Because of "being discarded", I believe the <xsl:apply-imports /> does not work recursively.
(There's no input for this stylesheet (well, it is run on any dummy input) and to keep things simple I left out a considerable amount of detail (namely: parameters, additional call-template and document('...') code etc).)
I know that one approach would be to use call-template for each xslt file with each match having another name. Another is to use different modes. A third might be to import as a hierarchical chain (i.e., let a import b import c etc). But all these loose much in terms of maintainability. I want one point for inclusion and one point only...
It is easy enough in XSLT 2.0, which brings us <xsl:next-match />, which will work as expected if placed in place of xsl:apply-imports.
Thanks for any thoughts. If it cannot be done, I just need a better approach, or a second transformation cycle, but I want to be sure before I try tackling this the hard way.
<xsl:import href="b.xslt" /> needs to be a.xslt, then it should work. In other words, the processing chain needs to be defined in the stylesheets themselves, not in one controlling transform.