我一直在努力弄清楚如何最好地模块化我的XSLT样式表以便于重复使用。我想到了使用< xsl:apply-imports />的想法。作为向标准标记转换引入特定于文档的属性的一种方式。这是不以我预期的方式工作,我甚至无法理解这里发生的事情。以下是样式表的简化版本:
Provider<HTTPRequest> mockHttpRequestProvider = mock(Provider.class);
when(mockHttpReqestProvider.get()).thenReturn(yourMockHTTPRequestObject);
// Set this mock provider to the ModelClass instance. (You may have to use reflection)
导入的样式表:
<!-- 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>
这是XML输入文件:
<!-- 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>
$ xalan -o out.xml test.xml main.xsl
<!-- 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>
如您所见,元素的每个子元素都与包含&lt; xsl:apply-imports /&gt;的模板匹配。重复!我包含了导入的样式表,以说明我正在尝试做什么。如果我注释掉这个导入:
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>
...
...
重复行为是相同的:
<!--
<xsl:import href="html-customizations.xsl"/>
-->
没有尝试从导入的样式表添加的属性;即只是&lt; xsl:apply-imports /&gt;的存在处理指令使输出元素加倍。另请注意,这不仅仅是 xalan 问题 - 在Windows 7上的MSXML上也会发生同样的事情。
有什么想法?我指望这个工作,所以我现在正在试着弄清楚如何解决这个问题,以便它有效。
BTW,我对如何&lt; xsl:apply-imports /&gt;的假设?可以使用的是基于Michael Kay的书的 xsl:import 部分给出的示例。如果有人知道解释我上面看到的行为的参考,请分享。
答案 0 :(得分:4)
我同意apply-imports
的行为很难理解。问题是apply-imports
总是找到与当前节点匹配的模板,即使用户没有定义它也是如此。在这种情况下,默认模板适用。
以下样式表有效:
XSLT样式表
<?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>
正如您所看到的,我删除了两个apply-imports
元素,只留下template/@match='td | th'
内的元素。然后,输出将是
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-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>
到底发生了什么?
apply-imports
寻找
现在,关键的一点是:如果在导入的样式表中找不到这样的模板,则该指令将调用built-in templates。如果是tr
:
<xsl:template match="tr">
<fo:table-row>
<xsl:apply-imports/>
<xsl:apply-templates/>
</fo:table-row>
</xsl:template>
元素节点的默认操作是遍历它并将模板应用于其内容,因此上面的代码段实际上转换为
<xsl:template match="tr">
<fo:table-row>
<xsl:apply-templates/>
<xsl:apply-templates/>
</fo:table-row>
</xsl:template>
这就是输出包含重复项的原因。我现在假设您也理解为什么评论xsl:import
没有帮助,否则我很乐意详细说明。
由于您还要求引用,所以 在 XSLT 2.0和XPath 2.0程序员参考中由Michael Kay解释,第238页。