从多个父项中选择最后一个节点

时间:2012-01-10 04:11:58

标签: xslt xpath

我有以下XML结构

<root>
 <entries>
  <object id="1">
   <value name="valName1">Text</value>
   <value name="valName2">Text</value>
   <value name="valName3">Text</value>
  </object>
  <object id="2">
   <value name="valName1">Text</value>
  </object>
  <object id="1">
   <value name="valName1">OtherText</value>
   <value name="valName2">Text</value>
  </object>
 </entries>
</root>

我想最终:

object: 1
valName1: OtherText
valName2: Text
valName3: Text

object: 2
valName1: Text

重要的是它返回值节点的最后一个数据,但它应该从它们存在的节点获取所有值...

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

这可以通过分组在纯XSLT中实现。在XLST 1.0中,您将使用Muenchian分组,在这种情况下,您需要两批分组。首先,您将按对象进行分组,这意味着定义一个按ID来查找对象元素的键

<xsl:key name="objects" match="object" use="@id" />

要查找每个组中的第一个元素(即唯一对象id),您可以使用如下键:

<xsl:apply-templates 
   select="//object[generate-id() = generate-id(key('objects', @id)[1])]" />

然后,您按进行分组,这意味着定义一个键以在其各自的对象元素中查找元素

<xsl:key name="values" match="value" use="concat(../@id, '|', @name)" />

在这种情况下,你真的需要每个组中的最后一个元素,所以你会像这样使用键:

<xsl:apply-templates 
   select="//object[@id = $id]
      /value[generate-id() 
       = generate-id(key('values', concat($id, '|', @name))[last()])]">

这是完整的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="text" indent="yes"/>
   <xsl:key name="objects" match="object" use="@id" />
   <xsl:key name="values" match="value" use="concat(../@id, '|', @name)" />

   <xsl:template match="/">
      <xsl:apply-templates select="//object[generate-id() = generate-id(key('objects', @id)[1])]" />
   </xsl:template>

   <xsl:template match="object">
      <xsl:variable name="id" select="@id" />
      <xsl:value-of select="concat('object: ', $id, '&#13;')" />
      <xsl:apply-templates select="//object[@id = $id]/value[generate-id() = generate-id(key('values', concat($id, '|', @name))[last()])]">
         <xsl:sort select="@name" />
      </xsl:apply-templates>
   </xsl:template>

   <xsl:template match="value">
      <xsl:value-of select="concat(@name, ':', ., '&#13;')" />
   </xsl:template>
</xsl:stylesheet>

当应用于提供的输入XML时,输出以下文本:

object: 1
valName1:OtherText
valName2:Text
valName3:Text
object: 2
valName1:Text

答案 1 :(得分:0)

这当然是可行的,但我会说你在某些方面错误地使用XML。我的理解是id标签通常是唯一的,文件的顺序无关紧要。尽管如此,使用Python很容易实现这一点。

使用字典。只需浏览该文件,然后在找到它们时将对象添加到字典中。您添加的“对象”实际上将对象ID作为索引,并且本身就是一个空白字典。跟踪您当前的对象并搜索每个值标记,将值名称和内容添加到当前对象的字典中。这将跟踪发现的最新数据。

作为替代方案,你可以等到明天我有时间为你写这个(明天在AP政府测试)。