使用类似参数调用模板两次

时间:2015-01-21 17:16:44

标签: xslt parameter-passing xslt-2.0

现在我有一个像这样的xml文件: 基本上所有标记都会出现两次,但前缀为sideAsideB

<root>
    <sideA_foo>abc</sideA_foo>
    <sideA_bar>123</sideA_bar>
    <sideA_foobar>xyz</sideA_foobar>
    <!--many more sideA... tags -->

    <sideB_foo>def</sideB_foo>
    <sideB_bar>456</sideB_bar>
    <sideB_foobar>uvw</sideB_foobar>
    <!--many more sideB... tags -->
</root>

然后我有一个这样的模板

<xsl:template name="template1">
    <xsl:param name = "foo"/>
    <xsl:param name = "bar"/>
    <xsl:param name = "foobar"/>
    <!-- many more params -->

    <!-- do anything here -->
</xsl:template>

是否有一种优雅的方式可以使用它的所有参数调用此模板两次,

  • <xsl:with-param name = "foo" select = "sideA_foo"/>等。
  • <xsl:with-param name = "foo" select = "sideB_foo"/>等。

没有把所有这些非常冗长,我讨厌吗?

1 个答案:

答案 0 :(得分:1)

以下是您可以考虑的一种方式:

给出示例输入

<root>
    <sideA_width>5</sideA_width>
    <sideA_length>7</sideA_length>
    <sideB_width>6</sideB_width>
    <sideB_length>3</sideB_length>
</root>

以下样式表:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/root">
    <output>
        <xsl:call-template name="side-area">
            <xsl:with-param name="side" select="'sideA'"/>
        </xsl:call-template>
        <xsl:call-template name="side-area">
            <xsl:with-param name="side" select="'sideB'"/>
        </xsl:call-template>
    </output>
</xsl:template>

<xsl:template name="side-area">
    <xsl:param name="side"/>
    <xsl:param name="width" select="*[name()=concat($side, '_width')]"/>
    <xsl:param name="length" select="*[name()=concat($side, '_length')]"/>
    <xsl:element name="{$side}_area">
        <xsl:value-of select="$width * $length"/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

将返回:

<?xml version="1.0" encoding="UTF-8"?>
<output>
   <sideA_area>35</sideA_area>
   <sideB_area>18</sideB_area>
</output>

但请注意,元素的显式命名效率更高 - 有时 更有效。 真正优雅的解决方案是在你的输入到达之前将其标准化,以便它看起来更像(例如):

<root>
    <rect id="X">
        <width>5</width>
        <length>7</length>
    </rect> 
    <rect id="Y">
        <width>6</width>
        <length>3</length>
    </rect> 
</root>