【问题标题】:template to similar fields in xsltxslt 中类似字段的模板
【发布时间】:2016-11-11 10:25:00
【问题描述】:

我的 xml 文件

...
<element1>
    <year>1</year>
    <month>5</month>
    <days>3</days>
</element1>

<element2>
    <year>2</year>
    <month>4</month>
    <days>5</days>
</element2>
...

我的 xsl-fo 模板

<fo:block>
    <xsl:value-of select="//element1/years"/>
    <xsl:text> years </xsl:text>
    <xsl:value-of select="//element1/month"/>
    <xsl:text> month </xsl:text>
    <xsl:value-of select="//element1/days"/>
    <xsl:text> days </xsl:text>
</fo:block>

...

<fo:block>
    <xsl:value-of select="//element2/years"/>
    <xsl:text> years </xsl:text>
    <xsl:value-of select="//element2/month"/>
    <xsl:text> month </xsl:text>
    <xsl:value-of select="//element2/days"/>
    <xsl:text> days </xsl:text>
</fo:block>

如您所见,这里有一个类似的代码块。 我怎样才能简化这个表达式? 应该使用什么样的模板?

我写了一个这样的模板

<xsl:template match="element1">
    <xsl:value-of select="years"/>
    <xsl:text> years </xsl:text>
    <xsl:value-of select="month"/>
    <xsl:text> month </xsl:text>
    <xsl:value-of select="days"/>
    <xsl:text> days </xsl:text>
</xsl:template>       

并使用它

<fo:block>
    <xsl:apply-templates select="element1"/>
</fo:block>

但它不适用于element2...

【问题讨论】:

  • 在不了解所有细节的情况下,我会说具有相同结构的两个元素“element1”和“element2”会散发出糟糕的 XML 设计气味,而我通常使用设计糟糕的 XML 输入的策略是拆分任务一分为二:首先进行一次转换以清理 XML 并将其转换为设计良好的 XML,然后再进行一次转换以完成真正的工作。

标签: xml xslt xsl-fo


【解决方案1】:

给定 XML(学分转到 @michael.hor257k):

<parent>
    <element1>
        <year>1</year>
        <month>5</month>
        <days>3</days>
        <hour>12</hour>
        <minute>32</minute>
    </element1>
    <element2>
        <year>2</year>
        <month>4</month>
        <days>5</days>
        <hour>0</hour>
    </element2>
</parent>

我。匹配模板模式中的多个元素

<xsl:template match="element1 | element2">
  <fo:block>
    <xsl:value-of select="year"/>
    <xsl:text> years </xsl:text>
    <xsl:value-of select="month"/>
    <xsl:text> month </xsl:text>
    <xsl:value-of select="days"/>
    <xsl:text> days </xsl:text>
  </fo:block>
</xsl:template>

二。调用模板

<xsl:template match="element1">
  <xsl:call-template name="renderOutput"/>
</xsl:template>

<xsl:template name="renderOutput">
  <fo:block>
    <xsl:value-of select="year"/>
    <xsl:text> years </xsl:text>
    <xsl:value-of select="month"/>
    <xsl:text> month </xsl:text>
    <xsl:value-of select="days"/>
    <xsl:text> days </xsl:text>
  </fo:block>
</xsl:template>

[默认情况下,调用模板中的上下文节点会获取调用者的上下文节点!不需要但也可以,继续使用&lt;xsl:with-param name="this" select="."/&gt;&lt;xsl:value-of select="$this/year"/&gt;]

【讨论】:

    【解决方案2】:

    好吧,给定:

    <parent>
      <element1>
        <year>1</year>
        <month>5</month>
        <days>3</days>
      </element1>
      <element2>
        <year>2</year>
        <month>4</month>
        <days>5</days>
      </element2>
    </parent>
    

    你可以这样做:

    <xsl:template match="parent">
        <fo:wrapper>
            <xsl:for-each select="*">
                <fo:block>
                    <xsl:value-of select="year"/>
                    <xsl:text> years </xsl:text>
                    <xsl:value-of select="month"/>
                    <xsl:text> months </xsl:text>
                    <xsl:value-of select="days"/>
                    <xsl:text> days </xsl:text>
                </fo:block>
            </xsl:for-each>
        </fo:wrapper>
    </xsl:template>
    

    得到:

    <fo:wrapper>
      <fo:block>1 years 5 months 3 days </fo:block>
      <fo:block>2 years 4 months 5 days </fo:block>
    </fo:wrapper>
    

    我不需要选择所有元素,我只想应用这种 模板到具有相似子元素的元素,在不同的地方

    在这种情况下,您可以调用一个命名模板 - 例如:

    <xsl:template match="element1">
        <xsl:call-template name="duration"/>
    </xsl:template>
    ...
    <xsl:template match="element1">
        <xsl:call-template name="duration"/>
    </xsl:template>
    ...    
    <xsl:template name="duration">
        <fo:block>
            <xsl:value-of select="year"/>
            <xsl:text> years </xsl:text>
            <xsl:value-of select="month"/>
            <xsl:text> months </xsl:text>
            <xsl:value-of select="days"/>
            <xsl:text> days </xsl:text>
        </fo:block>
    </xsl:template>
    

    【讨论】:

    • 我不需要选择所有元素,我只想将这种模板应用于具有相似子元素的元素,在不同的地方
    • @guesswho 请发布一个更具代表性的例子。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-12
    • 1970-01-01
    • 2021-12-01
    相关资源
    最近更新 更多