在XSLT中防止元素的多个定义

时间:2016-09-02 09:26:46

标签: xslt

我正在尝试编写一个XSLT样式表,它使用许多通用模板将一个XML文档复制到另一个XML文档中,以执行诸如在匹配节点上插入属性之类的操作。我遇到的问题是这些模板的要求是制作元素节点的副本,这意味着多次调用它将产生两个节点副本。

属性插入模板的编写方式如下:

<xsl:template match = "DO_NOT_MATCH" name = "InsertAttribute">
    <xsl:param name = "attributeName"/>
    <xsl:param name = "attributeValue"/>
    <xsl:element name = "{name(.)}">
        <xsl:copy-of select = "@*"/>
        <xsl:attribute name = "{$attributeName}">
            <xsl:value-of select = "$attributeValue"/>
        </xsl:attribute>
        <xsl:apply-templates />
    </xsl:element>
</xsl:template>

我这样称呼这个模板:

<xsl:template match="Object">
    <xsl:call-template name = "InsertAttribute">
        <xsl:with-param name = "attributeName" select = '"NewAttribute1"'/>
        <xsl:with-param name = "attributeValue" select = '4'/>
    </xsl:call-template>
    <xsl:call-template name = "InsertAttribute">
        <xsl:with-param name = "attributeName" select = '"NewAttribute2"'/>
        <xsl:with-param name = "attributeValue" select = '6'/>
    </xsl:call-template>
</xsl:template>

这将转换XML文档,如下所示:

<root>
    <Object/>
</root>

......进入这个:

<root>    
    <Object NewAttribute1="4"/>
    <Object NewAttribute2="6"/>
</root>

我正在寻找一种获得以下输出的方法,而不必连续使用两个不同的样式表,或者手动将两个模板调用组合到一个操作中。你们中的任何人都知道这样做的方法吗?

<root>    
    <Object NewAttribute1="4" NewAttribute2="6"/>
</root>

2 个答案:

答案 0 :(得分:0)

我会将对象创建和属性处理移动到另一个模板中,然后只在命名模板中创建新属性:

<xsl:template match = "DO_NOT_MATCH" name = "InsertAttribute">
    <xsl:param name = "attributeName"/>
    <xsl:param name = "attributeValue"/>
    <xsl:attribute name = "{$attributeName}">
        <xsl:value-of select = "$attributeValue"/>
    </xsl:attribute>
</xsl:template>


<xsl:template match="Object">
  <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:call-template name = "InsertAttribute">
        <xsl:with-param name = "attributeName" select = '"NewAttribute1"'/>
        <xsl:with-param name = "attributeValue" select = '4'/>
    </xsl:call-template>
    <xsl:call-template name = "InsertAttribute">
        <xsl:with-param name = "attributeName" select = '"NewAttribute2"'/>
        <xsl:with-param name = "attributeValue" select = '6'/>
    </xsl:call-template>
    <xsl:apply-templates/>
  </xsl:copy>
</xsl:template>

答案 1 :(得分:0)

恕我直言,你过度工程了。 XSLT已经包含了一个向当前元素添加属性的指令。我没有看到为同一目的使用命名模板可以获得什么好处。

在给定的示例中,您可以简单地执行:

<xsl:template match="Object">
     <xsl:copy>
        <xsl:attribute name="NewAttribute1">4</xsl:attribute>
        <xsl:attribute name="NewAttribute2">6</xsl:attribute>
     </xsl:copy>
</xsl:template>

甚至更简单:

<xsl:template match="Object">
     <Object NewAttribute1="4" NewAttribute2="6"/>
</xsl:template>

如果您的方案不在此方法范围内,请发布一个示例。