1

I'm wondering if there is such as thing as being able to group XML data based on the text within elements.

I have some XML similar to the following, dumbed down for simplicity:

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

I want to display the above data in the following way:

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

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

I've tried multiple approaches using all the different examples but I just can't hit right right use of XPath for this one. I just can't wrap my head around being able to display only the first instance of Bob but also be able to display all of Bob's food, which is spread across multiple instances of Bob. Any suggestions as to where I could start with this?

4

2 回答 2

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)
于 2013-06-28T00:11:10.730 回答
1

要使用 xslt-1.0 执行此操作,您应该查看Muenchian Method , 例如 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> 
于 2013-06-28T05:51:22.510 回答