2013-06-28 37 views
1

我想知道是否有这样的事情能够根据元素内的文本分组XML数据。基于节点值对XPath查询进行分组?

我有一些XML类似于以下,简单化为了简单:

<person> 
    <name>Bob</name> 
    <food>Apples</food> 
</person> 
<person> 
    <name>Billy</name> 
    <food>Bananas</food> 
</person> 
<person> 
    <name>Bob</name> 
    <food>Oranges</food> 
</person> 

我想通过以下方式来显示上述数据:

Person's Name: Bob 
Person's Food: Apples 
       Oranges 

Person's Name: Billy 
Person's Food: Bananas 

我试过多种方法使用所有不同的例子,但我不能正确使用这个XPath的正确使用。我无法围绕只能显示Bob的第一个实例,而是能够显示所有Bob的食物,这些食物分布在Bob的多个实例中。对于我可以从哪里开始的任何建议?

+1

你谷歌 “XSLT分组”?或者(我敢说)在XSLT教科书的索引中查找“分组”?是的,关于这个主题有大量的文献 - 对于XSLT 1.0来说非常棘手(Muenchian分组),对于XSLT 2.0来说非常简单(xsl:for-each-group)。 –

回答

1

要做到这一点与XSLT的1.0你应该看看Muenchian方法e.g this

因此试试这个:

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

    <xsl:key name="kPerson" match="person" use="name"/> 
    <xsl:template match="/*"> 
     <xsl:for-each select="person[count(. | key('kPerson', name)[1]) =1 ]"> 
      <xsl:variable name="pname" select="name" /> 
      <xsl:text>Person's Name: </xsl:text> 
      <xsl:value-of select="$pname"/> 
      <xsl:text>&#10;</xsl:text> 
      <xsl:for-each select="key('kPerson', $pname)" > 
       <xsl:choose> 
        <xsl:when test="position()=1">Person's Food: </xsl:when> 
        <xsl:otherwise> 
         <xsl:text>    </xsl:text> 
        </xsl:otherwise> 
       </xsl:choose> 
       <xsl:value-of select="food"/> 
       <xsl:text>&#10;</xsl:text> 
      </xsl:for-each> 

     </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 
2

您可以使用XPath 2(不包含xslt)做类似的事情,使用distinct-values来获取所有名称,然后为每个名称创建包含食物的字符串。

for $v in distinct-values(/person/name) return concat($v, ": ", string-join(/person[name = $v]/food, ", ")) 

回报(与类型的相关信息)

sequence: (string: Bob: Apples, Oranges, string: Billy: Bananas) 

或更多类似到您的输出:

for $v in distinct-values(/person/name) return concat(
    "Person's Name: ", $v, " 
Person's Food: ", string-join(/person[name = $v]/food, " 
       ")) 

回报

sequence: (string: Person's Name: Bob 
Person's Food: Apples 
       Oranges, string: Person's Name: Billy 
Person's Food: Bananas)