我正在编辑一个大型Microsoft InfoPath文档。InfoPath在内部使用XSLT进行表单布局。GUI非常麻烦,我想通过使用XSLT编辑内部样式表来加快这个过程。因此,这里有一个有趣的XSLT问题:如何将一个XSLT样式表应用于另一个?这里有一个开始:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="select">
...
<xsl:template>
</xsl:stylesheet>
也就是说,我复制所有内容,但更改<选择>元素。在"选择"模板中,我想要一块XSLT。但是,我不希望处理XSLT。但是我确实希望它有XSLT名称空间,这样输出仍然可以作为样式表工作。
我想我可以将XSLT块的名称空间URI设置为任何值,然后将其更改为XSLT名称空间URI,但这需要额外的步骤。有更好的方法吗?
这是<xsl:namespace-alias>
的目的
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:xslout="urn:dummy"
exclude-result-prefixes="xslout">
<xsl:namespace-alias stylesheet-prefix="xslout" result-prefix="xsl" />
<xsl:output method="xml" indent="yes"/>
<!-- ... -->
<xsl:template match="select">
<xslout:value-of select="{@valueXpath}" />
<xsl:template>
</xsl:stylesheet>
这里,样式表中的任何xslout:
元素都将在输出中变为xsl:
,并且这些元素中的任何属性值模板都将由这个样式表处理(因此在上面的例子中,<select valueXpath="@foo" />
将生成<xsl:value-of select="@foo" />
作为输出)。如果你想在输出中放入AVT,你必须将大括号加倍
<xslout:element name="{{@elementName}}" />
如果你已经有了不想重写的<xsl:...>
内容块,那么你可以使用不同的前缀,例如
<?xml version="1.0" encoding="utf-8"?>
<sty:stylesheet xmlns:sty="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:xsl="urn:dummy"
exclude-result-prefixes="xsl">
<sty:namespace-alias stylesheet-prefix="xsl" result-prefix="sty" />
<sty:template match="select">
<xsl:value-of select="{@valueXpath}" />
<sty:template>
尽管关于AVT的注释仍然有效。
如果您只想将一块XSLT代码逐字复制到select
元素中(而不是根据select
元素的内容生成它),一个可能更简单的替代方案是将该XSLT代码放在另一个文件中,并使用document
函数
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="select">
<xsl:copy-of select="document('to-insert.xml')/*/node()" />
<xsl:template>
</xsl:stylesheet>
其中to-insert.xml
包含类似的内容
<data xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:for-each select="*">
<!-- ... -->
</xsl:for-each>
</data>
要将XSLT元素输出到结果XML文档,您不能按原样使用这些元素,因为正如您所说,它们将作为XSLT处理。但是,您可以使用元素<xsl:element>输出XSLT元素。
例如,
<xsl:template match="select">
<xsl:element name="xsl:apply-templates">
<xsl:attribute name="select">*</xsl:attribute>
</xsl:element>
<xsl:template>
这将为每个选择元素输出
<xsl:apply-templates select="*" />
您可以使用<xsl:element>和<xsl:attribute>来构建要输出的XSLT代码。
UPDATE:根据您的场景,您有一个需要在选择模板中输出的大型XSLT代码,因此用<xsl:element>和<xsl:attribute>。但是您不需要花费那么多时间,因为您可以编写XSL模板来将模板匹配select中的XSLT转换为使用<xsl:element>和<xsl:attribute>。
以下代码可以做到这一点:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:myname="http://www.myname.co.uk/def">
<xsl:output method="xml" indent="no"/>
<!-- Copy by default all elements which do not belong to the xsl namespace -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<!-- Match elements which their namespace match the namespace matched with xsl -->
<xsl:template match="xsl:*">
<!-- Transform all the elements to xsl:element name="xsl:element" nodes -->
<xsl:element name="xsl:element">
<xsl:attribute name="name">
<xsl:value-of select="name()" />
</xsl:attribute>
<xsl:apply-templates select="@*" mode="xsl-attr" />
<xsl:apply-templates select="node()" />
</xsl:element>
</xsl:template>
<!-- Transform all the attributes to xsl:element name="xsl:attribute" -->
<xsl:template match="@*" mode="xsl-attr">
<xsl:element name="xsl:attribute">
<xsl:attribute name="name">
<xsl:value-of select="local-name()" />
</xsl:attribute>
<xsl:value-of select="." />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
因此,您可以将从转换中获得的代码复制并粘贴到与select元素匹配的模板中。