2012-10-08 35 views
1

我想了解XSLT中的分組。我有一個XML文檔,其中包含調查問卷的答案,由受訪者列出(「pid」)。我想按問題的答案對所有受訪者這樣我就可以創建圖表等。以下是基本的XML結構:XSLT多級分組:xsl:for-each-group with Muenchian方法

<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)分組技術結合起來,最終確實實現了它的功能。但是,我仍然不太明白它是如何工作的。這裏是我用來組XSLT位<answer>元素:

<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>元素?

是否有更簡單的方法來達到相同的結果?謝謝!

+0

有可能是一個更簡單的方法,沒有Muenchian分組,而是爲了幫助實現一個更簡單的方法我犯了d喜歡看到輸入樣本和相應的輸出樣本。當前輸入樣本似乎與您發佈的結果不匹配。 –

+0

謝謝。我已經更新了XSLT,以便根據輸入的XML生成與我的示例中格式完全一樣的示例輸出。 – tat

+0

對不起,還更新了XML輸入,以便它反映示例輸出。 – tat

回答

2

這可以簡化一點,而不需要muenchian分組(就像那樣可愛)。

您已經開始正確使用@key將問題分組了。

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

不過,對於每個問題,你需要看看所有的答案對特定問題,它們組合。您可以通過@key在這種情況下使用密鑰,將所有的答案對於一個給定的問題

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

然後,組答案,一個給定的問題之內,你仍然可以使用的xsl:for-每個-group

​​3210

即獲取問題的所有答案,並通過@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 
+0

清晰,細緻,優雅的解決方案。謝謝! – tat