2

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

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

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

4

2 回答 2

2

为了将 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 代码。

更新:根据您的场景,您有一个大型 XSLT 代码需要在选择模板中输出,因此使用 <xsl:element> 和 <xsl:attribute> 重写所有代码会很耗时。但是您不需要花费那么多时间,因为您可以编写一个 XSL 模板,将模板匹配 select 中的 XSLT 转换为用 <xsl:element> 和 <xsl:attribute> 编写的 XSL 代码。

以下代码将执行此操作:

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

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

于 2013-02-21T13:35:12.740 回答
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:输出,并且此类元素中的任何属性值模板都将由该样式表处理(因此在上面的 a<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>
于 2013-02-21T14:02:08.443 回答