【问题标题】:Generalizing XSLT code泛化 XSLT 代码
【发布时间】:2016-10-30 18:02:24
【问题描述】:

为了在不同的地方重用它们,我正在尝试了解泛化 XSLT 模板的不同可能性。到目前为止,我有两种情况我不知道如何进行。

案例 1 - 源 XML 可能包含节点 Foo1, Foo2, ..., Foo10(但不必包含任何或全部)。例如,

<Foo1>some value</Foo1>
<Foo3>some other value</Foo3>

我需要按如下方式创建节点:

<Bar number="1">some value</Bar>
<Bar number="3">some other value</Bar>

我的 XSLT 目前非常简单:

<xsl:if test="Foo1 != ''">
  <xsl:element name="Bar">
    <xsl:attribute name="number">1</xsl:attribute>
    <xsl:value-of select="Foo1"/>
  </xsl:element>
</xsl:if>

但我显然需要 10 个这样的代码块。我如何概括这一点?

案例 2 - 在源 XML 中,我有几个结构基本相同的节点:

<Foo>
  <item>
    <Start>2015-06-01</Start>
    <End>9999-12-31</End>
    <Foo>00000008</Foo>
  </item> <!-- 0..n items -->
</Foo>

节点名称 Foo 不同,但其余节点保持不变。我需要构建的结构如下所示:

<Bars>
  <Bar From="2015-06-01" To="9999-12-31">
    <Value>00000008</Value>
  </Bar>
</Bars>

这是我的 XSLT 尝试,但我需要许多彼此非常相似的模板:

<xsl:element name="Bars>
  <apply-templates select="Foo"/>
</xsl:element>

...

<xsl:template match="Foo/item">
  <xsl:element name="Bar">
    <xsl:attribute name="From">
      <xsl:call-template name="convertDate">
        <xsl:with-param name="theDate" select="Start"/>
      </xsl:call-template>
    </xsl:attribute>
    <xsl:attribute name="To">
      <xsl:call-template name="convertDate">
        <xsl:with-param name="theDate" select="End"/>
      </xsl:call-template>
    </xsl:attribute>
    <xsl:element name="Value">
      <xsl:value-of select="Foo"/>
    </xsl:element>
  </xsl:element>
</xsl:template>

再一次,我有几个模板,它们看起来都非常相似(即,它们仅在 FooBarValue 元素的名称上有所不同)。有没有机会概括这一点,即提供一个可以处理所有这些情况的模板?

【问题讨论】:

  • 对于 1) 您应该能够从序列中生成名称,对于 2) 您应该能够通过 xpath "last-child-of-item" (pseudo-xpath) 检索值.我现在没有时间给出完整的答案,但我会稍后再回来查看。
  • @Filburt 您能否详细说明您对 2) 的建议?我仍然对那个有点迷失......在此先感谢。

标签: xml templates xslt xslt-1.0 generalization


【解决方案1】:

你可以使用

<xsl:template match="*[starts-with(local-name(), 'Foo')]">
  <Bar number="{translate(local-name(), translate(local-name(), '1234567890', ''), '')}">
    <xsl:apply-templates/>
  </Bar>
</xsl:template>

第一个样本。

转换

  <item>
    <Start>2015-06-01</Start>
    <End>9999-12-31</End>
    <Foo>00000008</Foo>
  </item>

  <Bar From="2015-06-01" To="9999-12-31">
    <Value>00000008</Value>
  </Bar>

你可以使用

<xsl:template match="item">
  <Bar From="{Start}" To="{End}">
    <xsl:value-of select="Foo"/>
  </Bar>
</xsl:template>

【讨论】:

  • 我认为第二个没有解决 OP 问题:Foo 是我理解问题的任意元素,所以 &lt;xsl:value-of select="Foo"/&gt; 不起作用。
  • 诚然,我不确定第二个问题,“节点名称 Foo 不同”这句话是否与 item 元素的 Foo 容器或 Foo 子元素有关.
  • 感谢您的快速解答!我已经实现了您提供的第一个解决方案,只需将&lt;xsl:apply-templates/&gt; 替换为&lt;xsl:value-of select="." /&gt;(可能是因为我已经覆盖了相应的内置模板)。
  • 对于您的第二个解决方案,@Filburt 是正确的(抱歉不够精确):两个 Foo 元素都是任意的(但就我所见,总是具有相同的名称)。因此,Foo 引用了容器 子元素。
猜你喜欢
  • 1970-01-01
  • 2017-07-26
  • 1970-01-01
  • 2012-01-05
  • 2018-12-21
  • 1970-01-01
  • 2012-05-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多