【问题标题】:How to call a named xslt template on a specific node如何在特定节点上调用命名的 xslt 模板
【发布时间】:2016-10-10 15:14:54
【问题描述】:

我有一个非常统一的输入 XML,我需要将其转换为完全自定义的 XML。 为此,我尝试在 XSL 的不同位置调用名称模板。我的问题是调用模板时无法选择节点,导致这样的代码非常长且冗余(简化示例来说明问题):

<xsl:template match="/">

    <workspace>
       <data>
            <xsl:apply-templates select="/data/data_set[@id='id1']" />                  
            <xsl:apply-templates select="/data/data_set[@id='id2']" />                  
            <xsl:apply-templates select="/data/data_set[@id='id3']" />                  
       </data>
    </workspace>

</xsl:template>


<xsl:template match="/data/data_set[@id='id1']">            
    <xsl:call-template name="attribute">                            
        <xsl:with-param name="id" select="'some_value1'" />
        <xsl:with-param name="type" select="'some_value2'" />
    </xsl:call-template>
</xsl:template>

<xsl:template match="/data/data_set[@id='id2']">            
    <xsl:call-template name="attribute">                            
        <xsl:with-param name="id" select="'some_other_value1'" />
        <xsl:with-param name="type" select="'some_other_value2'" />
    </xsl:call-template>
</xsl:template>

<xsl:template match="/data/data_set[@id='id3']">            
    <xsl:call-template name="attribute">                            
        <xsl:with-param name="id" select="'some_third_value1'" />
        <xsl:with-param name="type" select="'some_third_value2'" />
    </xsl:call-template>
</xsl:template>

<xsl:template name="attribute">
    <xsl:param name="id" />
    <xsl:param name="type" />       

     <!-- Write the attribute node -->
    <attribute attribute_id="{$id}" attribute_value_type="{$type}">         
        <xsl:for-each select="data_point">
            <element>
                <xsl:attribute name="id"><xsl:value-of select="@key" /></xsl:attribute>
                <xsl:attribute name="{$type}"><xsl:value-of select="@value" /></xsl:attribute>                                          
            </element>
        </xsl:for-each>
    </attribute>            

</xsl:template>

有没有更好的方法来避免所有这些冗余?我想要写这样的东西(但这不是有效的 XSLT),因为你不能在调用模板中进行选择。

<xsl:template match="/">
    <workspace>
       <data>
        <xsl:call-template name="attribute" select="/data/data_set[@id='id1']">                         
            <xsl:with-param name="id" select="'some_value1'" />
            <xsl:with-param name="type" select="'some_value2'" />
        </xsl:call-template>
        <xsl:call-template name="attribute" select="/data/data_set[@id='id2']">                         
            <xsl:with-param name="id" select="'some_other_value1'" />
            <xsl:with-param name="type" select="'some_other_value2'" />
        </xsl:call-template>
        <xsl:call-template name="attribute" select="/data/data_set[@id='id3']">                         
            <xsl:with-param name="id" select="'some_third_value1'" />
            <xsl:with-param name="type" select="'some_thrid_value2'" />
        </xsl:call-template>           
       </data>
    </workspace>
</xsl:template>

示例输入:

<?xml version="1.0" encoding="utf-8"?>
<data>
      <data_set id="id1">
         <data_point value="1" key="4"/>
         <data_point value="2" key="5"/>
         <data_point value="3" key="6"/>
      </data_set>
      <data_set id="id2">
         <data_point value="1" key="4"/>
         <data_point value="2" key="5"/>
         <data_point value="3" key="6"/>
      </data_set>
      <data_set id="id3">
         <data_point value="1" key="4"/>
         <data_point value="2" key="5"/>
         <data_point value="3" key="6"/>
      </data_set>
</data>

示例输出:

<?xml version="1.0" encoding="utf-8"?>
<workspace>
    <data>
        <attribute id="some_value1" type="some_value2">
            <element id="4" some_value2="1"/>
            <element id="5" some_value2="2"/>
            <element id="6" some_value2="3"/>
        </attribute>
        <attribute id="some_other_value1" type="some_other_value2">
            <element id="4" some_other_value2="1"/>
            <element id="5" some_other_value2="2"/>
            <element id="6" some_other_value2="3"/>
        </attribute>
        <attribute id="some_third_value1" type="some_third_value2">
            <element id="4" some_third_value2="1"/>
            <element id="5" some_third_value2="2"/>
            <element id="6" some_third_value2="3"/>
        </attribute>
    </data>
</workspace>    

【问题讨论】:

  • 如果包含输入和预期输出的示例,问题会更好地说明。
  • 嗯,这仍然是一个谜,因为我们看不到被调用的模板做了什么。这些参数是完全任意的吗?或者它们可能以某种方式源自@id
  • 是否可以看到调用模板?也许我们可以解决这个问题。所以冗余也会减少。但我们看不到的,我们无法改变。
  • 参数甚至模板都可能因 id 而异。
  • @user3124206 也许您应该使用查找来确定它们。顺便说一句,您的示例显示为每个 id 调用相同的模板。

标签: xml xslt


【解决方案1】:

如果为被调用模板提供匹配的data_set 的上下文很重要,那么我建议您按照以下方式进行操作:

<xsl:template match="/data">
    <workspace>
       <data>
            <xsl:apply-templates select="data_set[@id='id1' or id='id2' or id='id3']" />                  
       </data>
    </workspace>
</xsl:template>

<xsl:template match="data_set">            
    <xsl:call-template name="attribute">  
        <xsl:with-param name="id">
            <xsl:choose>
                <xsl:when test="@id='id1'">some_value1</xsl:when>
                <xsl:when test="@id='id2'">some_other_value1</xsl:when>
                <xsl:when test="@id='id3'">some_third_value1</xsl:when>
            </xsl:choose>
        </xsl:with-param>
        <xsl:with-param name="type">
            <xsl:choose>
                <xsl:when test="@id='id1'">some_value2</xsl:when>
                <xsl:when test="@id='id2'">some_other_value2</xsl:when>
                <xsl:when test="@id='id3'">some_third_value3</xsl:when>
            </xsl:choose>
        </xsl:with-param>
    </xsl:call-template>
</xsl:template>

这是假设您使用的是 XSLT 1.0。在 XSLT 2.0 中可能会不那么冗长。

【讨论】:

  • 谢谢,我最终按照您的建议 + 使用 mode 做了一些事情,并且在详细程度方面得到了我相当满意的结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-07
  • 1970-01-01
  • 2023-04-04
  • 2014-07-23
  • 1970-01-01
  • 1970-01-01
  • 2022-01-10
相关资源
最近更新 更多