XSLT - 模板匹配冲突

XSLT - template match conflicts

我有一个 xml 如下,

<doc>
  <a ref="style1"></a>
  <a ref="style1"></a>
  <a ref="style1" ></a>
  <a ref="style2"></a>
  <a ref="style2"></a>
<doc>

我需要将 xslt 中的单独内容添加到 <a ref="style1"> 节点和 <a ref="style2"> 节点。我可以在 <xsl:template match ="a[@ref = 'style1']"><xsl:template match ="@ref = 'style2'"> 模板中编写那些需要的逻辑。

我还需要将动态 ID 添加到 <a> 节点。所以我写了下面的模板来添加所需的 ids

//adds dynamic id's to `<a>` nodes
<xsl:template match="a[@ref='style1' or @ref='style2']">
    <a ref="style">
        <xsl:attribute name="id">
            <xsl:number count="a[@ref='style1' or a[@ref='style2']"/>
        </xsl:attribute>
    </a>
</xsl:template>

我的预期输出如下,

<doc>
      <a ref="style" id="1"></a>
      <a ref="style" id="2"></a>
      <a ref="style" id="3"></a>
      <a ref="style" id="4"></a>
      <a ref="style" id="5"></a>
 <doc>

但由于我在两个地方(<xsl:template match ="a[@ref = 'style1']"><xsl:template match="a[@ref='style1' or @ref='style2']">)使用了相同的模板,所以在氧气编辑器中出现 "Ambiguous rule match" 错误。在这种情况下,我如何组织我的代码结构来避免这个错误?

一个选项是使处理 style1style2 的模板成为模版模板。

XML 输入

<doc>
    <a ref="style1"/>
    <a ref="style1"/>
    <a ref="style1"/>
    <a ref="style2"/>
    <a ref="style2"/>
</doc>

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="a[@ref='style1' or @ref='style2']" mode="addId">
        <xsl:apply-templates select="@*"/>
        <xsl:attribute name="ref" select="'style'"/>
        <xsl:attribute name="id">
            <xsl:number count="a[@ref=('style1','style2')]"/>
        </xsl:attribute>       
    </xsl:template>

    <xsl:template match="a[@ref='style1']">
        <xsl:copy>
            <xsl:apply-templates select="." mode="addId"/>
            <xsl:apply-templates select="node()"/>
            <special>processed style1</special>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="a[@ref='style2']">
        <xsl:copy>
            <xsl:apply-templates select="." mode="addId"/>
            <xsl:apply-templates select="node()"/>
            <special>processed style2</special>
        </xsl:copy>
    </xsl:template>    

</xsl:stylesheet>

输出

<doc>
   <a ref="style" id="1">
      <special>processed style1</special>
   </a>
   <a ref="style" id="2">
      <special>processed style1</special>
   </a>
   <a ref="style" id="3">
      <special>processed style1</special>
   </a>
   <a ref="style" id="4">
      <special>processed style2</special>
   </a>
   <a ref="style" id="5">
      <special>processed style2</special>
   </a>
</doc>

根据您对 style1style2 的个人模板的处理方式,您是否可以向通用模板添加更高的优先级,然后使用 xsl:next-match 匹配较低优先级的模板(个别处理)...

XSLT 2.0(使用上面的输入产生相同的输出)

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="a[@ref='style1' or @ref='style2']" priority="1">
        <a ref="style">
            <xsl:apply-templates select="@*"/>
            <xsl:attribute name="id">
                <xsl:number count="a[@ref=('style1','style2')]"/>
            </xsl:attribute>
            <xsl:next-match/>
        </a>
    </xsl:template>

    <xsl:template match="a[@ref='style1']">
        <special>processed style1</special>
    </xsl:template>

    <xsl:template match="a[@ref='style2']">
        <special>processed style2</special>
    </xsl:template>    

</xsl:stylesheet>