代码之家  ›  专栏  ›  技术社区  ›  OMG Ponies

xslt:合并样式表

  •  0
  • OMG Ponies  · 技术社区  · 15 年前

    我目前正在使用两个样式表来获得预期的输出。第一个样式表(pass1.xsl)完成了真正的工作,第二个样式表(pass2.xsl)在提供次要格式更新的同时删除了重复项。

    我的问题是是否可以在一个样式表中执行这两个操作。
    当我查看内容时,我无法通过xsl:functions获得这样的印象,因为两个样式表都包含模板匹配项,如果我从第二个样式表复制/粘贴到第一个样式表中,这些模板匹配项会发生冲突。IE:

    PAS1.XSL:

    <xsl:template match="xs:complexType">
      <xsl:param name="prefix" />       
      <xs:complexType name="{my:updateName($prefix, @name)}">
    
        <!-- insert xs:sequence ONLY if the child is NOT xs:complexContent -->
        <xsl:choose>
          <xsl:when test="*[name()='xs:complexContent']">
            <xsl:apply-templates select="node()" />
          </xsl:when>
          <xsl:otherwise>
            <xs:sequence>
              <xsl:apply-templates select="node()" />
            </xs:sequence>              
          </xsl:otherwise>
        </xsl:choose>
      </xs:complexType>
      <xsl:apply-templates select=".//xs:element" />
    </xsl:template>
    

    PAS2.XSL:

    <xsl:template match="xs:complexType">
      <xsl:copy>
        <xsl:apply-templates select="*|@*"/>
      </xsl:copy>
    </xsl:template>
    

    重申一下——目标是只运行一个样式表来生成最终结果。 跑两个并不难,但最好不要这么做。我是在复制/粘贴到原始文件中,还是在导入/包含我应该看到的内容?我希望只有一个样式表文件-以尽量减少有人错误删除支持文件的机会。

    1 回复  |  直到 15 年前
        1
  •  1
  •   Pavel Minaev    15 年前

    你应该用不同的 modes 对于模板(这需要添加 mode 属性到所有 xsl:template xsl:apply-templates 陈述)。然后,默认模式下根节点的模板将首先在第一种模式下触发根模板,然后在第二种模式下将结果传递给根模板。为此,您需要能够将结果树片段(这是元素构造函数生成的)视为节点集(这是您可以将模板应用到的节点集,或者通过xpath进行查询的节点集)-没有标准的方法可以做到这一点,但是 exsl:node-set 是一个事实上的标准(请注意,支持它的处理器的完整列表大于该页上的内容-例如,.net XslCompiledTransform 支持它)。所以:

    <xsl:template match="/">
       <xsl:variable name="round1-output">
         <xsl:apply-templates select="/" mode="round1" />
       </xsl:variable>
       <xsl:apply-templates select="exsl:node-set($round1-output)" mode="round2" />
    </xsl:template>
    
    <xsl:template match="/" mode="round1">
       ...
       <xsl:apply-templates mode="round1" />
       ...
    </xsl:template>
    
    <xsl:template match="/" mode="round2">
       ...
       <xsl:apply-templates mode="round2" />
       ...
    </xsl:template>
    
    ...
    
    <xsl:template match="xs:complexType" mode="round1">
      <xsl:param name="prefix" />           
      <xs:complexType name="{my:updateName($prefix, @name)}">
        <!-- insert xs:sequence ONLY if the child is NOT xs:complexContent -->
        <xsl:choose>
          <xsl:when test="*[name()='xs:complexContent']">
            <xsl:apply-templates select="node()" mode="round1"/>
          </xsl:when>
          <xsl:otherwise>
            <xs:sequence>
              <xsl:apply-templates select="node()" mode="round1"/>
            </xs:sequence>                          
          </xsl:otherwise>
        </xsl:choose>
      </xs:complexType>
      <xsl:apply-templates select=".//xs:element" mode="round1"/>
    </xsl:template>
    
    <xsl:template match="xs:complexType" mode="round2">
      <xsl:copy>
        <xsl:apply-templates select="*|@*" mode="round2"/>
      </xsl:copy>
    </xsl:template>