1

我试图理解 XSLT 中的分组。我有一个 XML 文档,其中包含调查问卷的答案,由受访者(“pid”)列出。我想按问题对所有受访者的答案进行分组,以便我可以创建图表等。这是基本的 XML 结构:

<survey>
    <answers>
        <pid xml:id="p1">
            <category key="#c1">
                <head>Category Heading</head>
                ... 
                <question key="#q1.4">
                    <answer key="#a2"/>
                    <answer key="#a3"/>
                    <answer key="#a4"/>
                </question
                ...
            </category
            ...
        </pid> 
        <pid xml:id="p2">
            <category key="#c1">
                <head>Category Heading</head>
                ... 
                <question key="#q1.4"> 
                    <answer key="#a2"/>
                    <answer key="#a3"/>
                    <answer key="#a4"/>
                </question
                ...
            </category
            ...
        </pid>   
        <pid xml:id="p3">
            <category key="#c1">
                <head>Category Heading</head>
                ... 
                <question key="#q1.4"> 
                    <answer key="#a2"/>                   
                </question
                ...
            </category
            ...
        </pid>   
        <pid xml:id="p4">
            <category key="#c1">
                <head>Category Heading</head>
             ... 
            <question key="#q1.4">
                <answer key="#a1"/>                                                             
            </question
            ...
            </category
            ...
        </pid>   
    </answers>
</survey>

我还想计算受访者中每个答案的出现次数。我尝试单独使用 XSLT 2.0 for-each-group,但无法让它按照我想要的方式工作。我最终将它与 Muenchian (XSLT 1.0) 分组技术结合起来,并最终让它发挥作用。但是,我仍然不明白它是如何工作的。这是我用来对<answer>元素进行分组的 XSLT 位:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
    exclude-result-prefixes="#all"
    version="2.0">
    <xsl:output encoding="iso-8859-1" method="text"
        omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>     

    <xsl:key name="answerKey" match="answer" use="@key"/>
    <xsl:key name="answerKey3" match="answer" use="concat(generate-id(..),' ',@key)"/>

    <xsl:template match="/">
    ...
        <xsl:for-each-group select="/survey/answers/pid/category/question" group-by="@key">          
            <xsl:variable name="qKey" select="@key"/>
            <xsl:variable name="x" select="generate-id(.)"/>  
            <xsl:text>
            </xsl:text>
            <xsl:value-of select="substring-after(@key,'#')"/>                                            
            <xsl:for-each-group select="//answer[count(.|key('answerKey3',concat($x,' ',@key))[1])=1][parent::question[@key=$qKey]]" group-by="@key">
            <xsl:text>
            </xsl:text>    
                <xsl:variable name="aID" select="substring-after(@key,'#')"/>                               
                <!-- <xsl:value-of select="key('questionKey2',parent::question/@key)/Answers/Answer[@xml:id=$aID]"/> -->                
                <xsl:value-of select="substring-after(@key,'#')"/>                        
                <xsl:text>,</xsl:text>                                                       
                <xsl:value-of select="count(key('answerKey',@key)[ancestor::question[@key=$qKey]])"/>                 
            </xsl:for-each-group>  
            <xsl:text>
            </xsl:text>
        </xsl:for-each-group>
    </xsl:template>
</xsl:stylesheet>

使用此代码,我可以输出以逗号分隔的答案列表和按问题分组的答案计数,例如:

q1.4
a1,1
a2,3
a3,2
a4,2

谁能解释这是如何工作的,尤其是for-each-group使用 Muenchian XPath 对我的<answer>元素进行分组的第二个(嵌套)?

有没有更简单的方法来达到同样的效果?谢谢!

4

1 回答 1

2

这可以在不需要 muenchian 分组的情况下稍微简化(尽管如此可爱)。

你已经正确地开始了,通过他们的@key对问题进行分组。

<xsl:for-each-group select="/survey/answers/pid/category/question" group-by="@key">

但是,对于每个问题,您需要查看该特定问题的所有答案,并将它们分组。在这种情况下,您可以使用一个键来对给定问题的所有答案进行分组

<xsl:key name="answerKey" match="answer" use="../@key"/>

然后,要按@key 对答案进行分组,在给定的问题中,您仍然可以使用xsl:for-each-group

<xsl:for-each-group select="key('answerKey', current-grouping-key())" group-by="@key">

即获取问题的所有答案,并按@key 属性对它们进行分组。此实例中的 current-grouping-key() 包含当前问题的 @key 属性。

最后,直接给出分组答案的总数

<xsl:value-of 
  select="concat(current-grouping-key(), ',', count(current-group()), '&#10;')" />

这是完整的 XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" exclude-result-prefixes="#all" version="2.0">
   <xsl:output encoding="iso-8859-1" method="text" omit-xml-declaration="yes" indent="yes"/>
   <xsl:strip-space elements="*"/>
   <xsl:key name="answerKey" match="answer" use="../@key"/>

   <xsl:template match="/"> 
      <xsl:for-each-group select="survey/answers/pid/category/question" group-by="@key">
         <xsl:value-of select="concat(current-grouping-key(), '&#10;')" />
         <xsl:for-each-group select="key('answerKey', current-grouping-key())" group-by="@key">
            <xsl:sort select="@key" />
            <xsl:value-of select="concat(current-grouping-key(), ',', count(current-group()), '&#10;')" />
         </xsl:for-each-group>
      </xsl:for-each-group>
   </xsl:template>
</xsl:stylesheet>

当应用于您的 XML 时,将输出以下内容

#q1.4
#a1,1
#a2,3
#a3,2
#a4,2
于 2012-10-09T08:37:14.963 回答