XSLT帮助 - XSL用于各种类似的XML,模板用法

时间:2011-11-11 08:32:01

标签: templates xslt xpath

我是XSL和XPath的新手。抱歉,如果这个问题显示出一些愚蠢。

我有一个类似

的XML
<root>
    <widget name="status">
    ...
        <component name="date">
            <component name="day" label="Fri"/>
            <component name="date" label="4"/>
        </component>
        <component name="time" label="11:23 AM"/>
    ....
    </widget>
    <widget name="foo">
    </widget>
</root>

我需要创建一个DateTime标记,它由所有三个值组成 周五上午11:23

我正在为它写一个XSL。

<DateTime>
    <xsl:value-of select="(//widget[@name="status"]/component[@name='date'])[1]/@label"/>
    <xsl:text> </xsl:text>
    <xsl:value-of select="(//widget[@name="status"]/component[@name='date'])[2]/@label"/>
    <xsl:text> </xsl:text>
    <xsl:value-of select="//widget[@name="status"]/component[@name='time']/@label"/>
</DateTime>

问题:

  1. 我将“widget [@ name =”date“]”传递给每个select语句。有没有更好的方法来缩短xpath。

  2. 我需要将其移动到模板中并调用模板。哪一个我应该使用call-template / apply-templates?

  3. 我们有一组生成这些XML的类似应用程序。上面的XML来自applicationA。 ApplicationB可能会以稍微不同的方式显示细节,例如<component name="datetime">Fri 4 11:23 AM</component>。我们有近3-4个这样的应用程序,它们以稍微不同的方式显示细节。

  4. DateTime只是一个例子,我还需要从这些不同的应用程序中捕获一些其他细节。

    我正在考虑编写一个XSL来处理所有应用程序。

2 个答案:

答案 0 :(得分:1)

使用XML执行此操作的一种方法是:

<xsl:template match="widget">
  <!-- ... -->
  <xsl:apply-templates select="." mode="create-date-time" />
  <!-- ... -->
</xsl:template>

<xsl:template match="widget" mode="create-date-time">
  <xsl:variable name="date" select="component[@name='date']" />
  <xsl:variable name="time" select="component[@name='time']" />

  <DateTime>
    <xsl:value-of select="normalize-space(
      concat(
        $date/component[@name='day']/@label, ' ', 
        $date/component[@name='date']/@label, ' ',
        $time/@label
      )
    )" />
  </DateTime>
</xsl:template>
  
      
  • 我将widget[@name="date"]传递给每个select语句。有没有更好的方法来缩短xpath。
  •   

使用<xsl:template> / <xsl:apply-templates>和相对路径。在<xsl:variable>中多次存储您需要的内容。见上文。

  
      
  • 我需要将其移动到模板中并调用模板。哪一个我应该使用call-template / apply-templates?
  •   

后者。总是去<xsl:apply-templates>,除非有充分理由不这样做。根据经验:如果你不确定,那就没有充分的理由。

  
      
  • 我们有一组生成这些XML的类似应用程序。上面的XML来自applicationA。 ApplicationB可能会以稍微不同的方式显示细节,例如<component name="datetime">Fri 4 11:23 AM</component>我们有近3-4个这样的应用程序,它们以稍微不同的方式显示细节。
  •   

您可以展开create-date-time模板以适应此目的:

<xsl:template match="widget" mode="create-date-time">
  <xsl:variable name="date" select="component[@name='date']" />
  <xsl:variable name="time" select="component[@name='time']" />
  <xsl:variable name="dt"   select="component[@name='datetime']" />

  <DateTime>
    <xsl:value-of select="normalize-space(
      concat(
        $dt/label, ' ',
        $date/component[@name='day']/@label, ' ', 
        $date/component[@name='date']/@label, ' ',
        $time/@label
      )
    )" />
  </DateTime>
</xsl:template>

如果缺少某些组件,则不会出错。 normalize-space()确保任何组件组合都没有多余的空格。

如果date + timedatetime组件不相互排斥(我假设它们是),则上述情况可能会失败。如果不是,或者如果出现更复杂的情况,请创建其他特定模板,如下所示:

<xsl:template match="widget[component[name='datetime']]" mode="create-date-time">
  <xsl:variable name="dt"   select="component[@name='datetime']" />

  <DateTime>
    <xsl:value-of select="component[@name='datetime']/@label" />
  </DateTime>
</xsl:template>

<xsl:apply-templates>将确保调用正确的一个。只需为每个可能发生的案例创建特定的match=表达式。

答案 1 :(得分:0)

这个简单的转换(16行,单个模板,完全“推”式,无变量,无模式):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match=
 "component
    [contains('|day|date|time|',
              concat('|', @name, '|'))
    ]
 ">
     <xsl:value-of select="concat(@label, ' ')"/>
     <xsl:apply-templates/>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

应用于提供的XML文档

<root>
    <widget name="status">
    ...
        <component name="date">
            <component name="day" label="Fri"/>
            <component name="date" label="4"/>
        </component>
        <component name="time" label="11:23 AM"/>
    ....
    </widget>
    <widget name="foo">
    </widget>
</root>

产生完全想要的结果

 Fri 4 11:23 AM