订购和删除属性中的数据

时间:2012-02-06 00:55:42

标签: xml xslt xpath

每个<leg>记录旅行的一段。旅程按文件顺序记录。一些腿在相同位置开始和结束(例如,从MA到MA),一些腿到位(例如,从MA到CT)。一些关于起点和终点位置的数据缺失。

<trip>
  <leg start="MA" stop="MA" />
  <leg start="MA" stop="CT" /> 
  <leg start="NY"           />
  <leg                      />
  <leg start="DE"           />
  <leg            stop="DE" />
  <leg start="NY" stop="PA" />
</trip>

使用XSLT / XPATH 1.0,我想按照访问顺序列出一个位置:

<trip>
  <place>MA</place>
  <place>CT</place>
  <place>NY</place>
  <place>DE</place>
  <place>NY</place>
  <place>PA</place>
</trip>

修改

好的,我想我知道该怎么做了:

<xsl:template match="leg" mode="tour">
    <xsl:if test="string(@start)">
        <place><xsl:value-of select="@start"></place>
    </xsl:if>
    <xsl:if test="string(@end)">
        <place><xsl:value-of select="@end"></place>
    </xsl:if>
</xsl:template>


<xsl:variable name="rtfPlaces">
    <xsl:apply-templates select="trip/leg" mode="tour" />
</xsl:variable>

<xsl:variable name="places" select="exslt:node-set($rtfPlaces)" />

<xsl:variable name="uniquePlaces" select="$places/place[1] | $places/place[.!=preceding-sibling::place[1]]" /> 

解决方案:确实在两次通过中处理它。通过单独写出来获取所需顺序的@start和@end。然后在第二遍中选择唯一值。

这不会让我得到输出中的trip元素,但我认为我真的不需要它。

它确实需要节点集扩展,但也可以。

如果一切都可以完成,我不知道如何。

1 个答案:

答案 0 :(得分:1)

这应该一次通过......

XML输入

<trip>
  <leg start="MA" stop="MA" />
  <leg start="MA" stop="CT" />
  <leg start="NY"           />
  <leg                      />
  <leg start="DE"           />
  <leg            stop="DE" />
  <leg start="NY" stop="PA" />
</trip>

XSLT 1.0

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

  <xsl:template match="node()|@*">
    <xsl:apply-templates select="node()|@*"/>
  </xsl:template>

  <xsl:template match="trip">
    <trip>
      <xsl:apply-templates/>
    </trip>
  </xsl:template>

  <!--This is so we don't get duplicate entries 
    for both attributes when they are the same.-->
  <xsl:template match="@stop[.=parent::*/@start]"/>

  <xsl:template match="@start|@stop">
    <xsl:if test="not(parent::leg/preceding-sibling::leg[1][@start = current() or @end = current()])">
      <place><xsl:value-of select="."/></place>      
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>

XML输出

<trip>
   <place>MA</place>
   <place>CT</place>
   <place>NY</place>
   <place>DE</place>
   <place>NY</place>
   <place>PA</place>
</trip>

您还可以添加此模板,以确保在@start之前@stop处理 <xsl:template match="leg"> <xsl:apply-templates select="@start"/> <xsl:apply-templates select="@stop"/> </xsl:template>

{{1}}