xml - Unanticipated <xsl:apply-imports/> behavior -
i've been trying figure out how best modularize xslt stylesheets facilitate re-use. hit upon idea of using <xsl:apply-imports/> way of introducing document-specific attributes standard tag transformations. not working way expected would, , can't begin fathom going on here. here simplified version of stylesheet:
<!-- main.xsl --> <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform" xmlns:fo="http://www.w3.org/1999/xsl/format"> <xsl:import href="html-customizations.xsl"/> <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/> <xsl:template match="para"> <fo:block> <xsl:attribute name="space-after">1em</xsl:attribute> <xsl:apply-templates/> </fo:block> </xsl:template> <!-- =============== --> <!-- inline elements --> <!-- =============== --> <xsl:template match="i"> <fo:inline font-style="italic"> <xsl:apply-imports/> <xsl:apply-templates/> </fo:inline> </xsl:template> <!-- ================ --> <!-- tables --> <!-- ================ --> <xsl:template match="table"> <fo:table> <xsl:apply-imports/> <xsl:apply-templates/> </fo:table> </xsl:template> <xsl:template match="tr"> <fo:table-row> <xsl:apply-imports/> <xsl:apply-templates/> </fo:table-row> </xsl:template> <xsl:template match="td | th"> <fo:table-cell> <xsl:apply-imports/> <xsl:apply-templates/> </fo:table-cell> </xsl:template> </xsl:stylesheet>
the imported stylesheet:
<!-- html-customizations.xsl --> <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform" xmlns:fo="http://www.w3.org/1999/xsl/format"> <xsl:template match="td | th"> <xsl:attribute name="hyphenate">true</xsl:attribute> </xsl:template> </xsl:stylesheet>
here xml input file:
<!-- test.xml --> <para> <table> <tr><td>spongebob squarepants, <i>chair</i></td></tr> <tr><td>patrick starfish, <i>vice cchair</i></td></tr> <tr><td>squidword, <i>secretary</i></td></tr> </table> </para>
$ xalan -o out.xml test.xml main.xsl
out.xml: <?xml version="1.0" encoding="utf-8"?> <fo:block xmlns:fo="http://www.w3.org/1999/xsl/format" space-after="1em"> <fo:table> <fo:table-row> <fo:table-cell hyphenate="true">spongebob squarepants, <fo:inline font-style="italic">chairchair</fo:inline> </fo:table-cell> <fo:table-cell hyphenate="true">spongebob squarepants, <fo:inline font-style="italic">chairchair</fo:inline> </fo:table-cell> </fo:table-row> <fo:table-row> <fo:table-cell hyphenate="true">patrick starfish, <fo:inline font-style="italic">vice cchairvice cchair</fo:inline> </fo:table-cell> <fo:table-cell hyphenate="true">patrick starfish, <fo:inline font-style="italic">vice cchairvice cchair</fo:inline> </fo:table-cell> </fo:table-row> <fo:table-row> <fo:table-cell hyphenate="true">squidword, <fo:inline font-style="italic">secretarysecretary</fo:inline> </fo:table-cell> <fo:table-cell hyphenate="true">squidword, <fo:inline font-style="italic">secretarysecretary</fo:inline> </fo:table-cell> </fo:table-row> <fo:table-row> <fo:table-cell hyphenate="true">spongebob squarepants, <fo:inline font-style="italic">chairchair</fo:inline> ... ...
as can see, every child of element matched template includes <xsl:apply-imports/> repeated! included imported stylesheet in order illustrate i'm trying do. if comment out import:
<!-- <xsl:import href="html-customizations.xsl"/> -->
the repeating behavior same:
<?xml version="1.0" encoding="utf-8"?> <fo:block xmlns:fo="http://www.w3.org/1999/xsl/format" space-after="1em"> <fo:table> <fo:table-row> <fo:table-cell>spongebob squarepants, <fo:inline font-style="italic">chairchair</fo:inline>spongebob squarepants, <fo:inline font-style="italic">chairchair</fo:inline> </fo:table-cell> <fo:table-cell>spongebob squarepants, <fo:inline font-style="italic">chairchair</fo:inline>spongebob squarepants, <fo:inline font-style="italic">chairchair</fo:inline> </fo:table-cell> </fo:table-row> <fo:table-row> ... ...
sans attribute i'm trying add imported stylesheet; i.e. presence of <xsl:apply-imports/> processing instruction causes output elements doubled. note not xalan problem -- same thing happens on msxml on windows 7.
any thoughts? counting on working, pulling hair out trying figure out how fix works.
btw, assumptions of how <xsl:apply-imports/> can used based on examples given under xsl:import section of michael kay's book. if knows of reference explains behavior i'm seeing above, please share.
i agree behaviour of apply-imports
difficult understand. problem apply-imports
always finds template matches current node, if user did not define it. in case, default template applies.
the following stylesheet works:
xslt stylesheet
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform" xmlns:fo="http://www.w3.org/1999/xsl/format"> <xsl:import href="html-customizations.xsl"/> <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/> <xsl:template match="para"> <fo:block> <xsl:attribute name="space-after">1em</xsl:attribute> <xsl:apply-templates/> </fo:block> </xsl:template> <!-- =============== --> <!-- inline elements --> <!-- =============== --> <xsl:template match="i"> <fo:inline font-style="italic"> <xsl:apply-templates/> </fo:inline> </xsl:template> <!-- ================ --> <!-- tables --> <!-- ================ --> <xsl:template match="table"> <fo:table> <xsl:apply-templates/> </fo:table> </xsl:template> <xsl:template match="tr"> <fo:table-row> <xsl:apply-templates/> </fo:table-row> </xsl:template> <xsl:template match="td | th"> <fo:table-cell> <xsl:apply-imports/> <xsl:apply-templates/> </fo:table-cell> </xsl:template> </xsl:stylesheet>
as can see, have removed 2 apply-imports
elements, leaving 1 inside template/@match='td | th'
. then, output be
xml output
<?xml version="1.0" encoding="utf-8"?> <fo:block xmlns:fo="http://www.w3.org/1999/xsl/format" space-after="1em"> <fo:table> <fo:table-row> <fo:table-cell hyphenate="true">spongebob squarepants, <fo:inline font-style="italic">chairchair</fo:inline> </fo:table-cell> </fo:table-row> <fo:table-row> <fo:table-cell hyphenate="true">patrick starfish, <fo:inline font-style="italic">vice cchairvice cchair</fo:inline> </fo:table-cell> </fo:table-row> <fo:table-row> <fo:table-cell hyphenate="true">squidword, <fo:inline font-style="italic">secretarysecretary</fo:inline> </fo:table-cell> </fo:table-row> </fo:table> </fo:block>
what happening?
apply-imports
looks template that
- matches current node
- matches current mode
- is inside imported stylesheet
now, crucial bit is: instruction invoke built-in templates if no such template can found in imported stylesheet. in case of tr
:
<xsl:template match="tr"> <fo:table-row> <xsl:apply-imports/> <xsl:apply-templates/> </fo:table-row> </xsl:template>
the default action element nodes traversing , applying templates content, snippet above translates to
<xsl:template match="tr"> <fo:table-row> <xsl:apply-templates/> <xsl:apply-templates/> </fo:table-row> </xsl:template>
and why output contains duplicates. assume understand why commenting out xsl:import
did not help, otherwise i'm glad elaborate.
since asking reference, is explained in xslt 2.0 , xpath 2.0 programmer's reference michael kay, page 238.
Comments
Post a Comment