将样式表应用于样式表?

时间:2013-02-21 13:29:49

标签: xslt

我正在编辑一个大型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>

也就是说,我复制了所有内容,但更改了&lt; select&gt;元素。在“选择”模板中,我想要一大块XSLT。但是,我希望处理XSLT。但我希望它拥有XSLT命名空间,以便输出仍然可以用作样式表。

我想我可以将XSLT块的名称空间URI设置为任何内容,然后将其更改为XSLT名称空间URI,但这需要额外的步骤。有更好的方法吗?

2 个答案:

答案 0 :(得分:2)

为了将XSLT元素输出到结果XML文档,您不能按原样使用这些元素,因为正如您所说,它们将被处理为XSLT。但是,您可以使用元素&lt; xsl:element&gt;输出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="*" />

您可以使用&lt; xsl:element&gt;和&lt; xsl:attribute&gt;构建您想要输出的XSLT代码。

更新:根据您的场景,您有一个需要在选择模板中输出的大型XSLT代码,因此使用&lt; xsl:element&gt;重写所有代码将非常耗时。和&lt; xsl:attribute&gt;。但是您不需要花费那么多时间,因为您可以编写一个XSL模板来将XSLT转换为使用&lt; xsl:element&gt;写入的XSL代码,该XSLT位于匹配select的模板内部。和&lt; xsl:attribute&gt;。

以下代码会这样做:

<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>

因此,您可以将从该转换中获得的代码复制并粘贴到与选择元素匹配的模板中。

答案 1 :(得分:2)

这是<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>