我试图理解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
任何人都可以解释这是如何工作的,尤其是使用Muenchian XPath对我的for-each-group
元素进行分组的第二个(嵌套)<answer>
吗?
是否有更简单的方法可以达到相同的效果?谢谢!
答案 0 :(得分: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()), ' ')" />
这是完整的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(), ' ')" />
<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()), ' ')" />
</xsl:for-each-group>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
应用于XML时,输出以下内容
#q1.4
#a1,1
#a2,3
#a3,2
#a4,2