2014-01-22 33 views
2

我想在xml元素上使用xslt進行分組,以便實際上不會共享任何常見值,並且我不確定我是否應該使用muenchian grouping或者不是,儘管我已經使用此方法在我的代碼中分組了我的元素。我也在論壇中搜索,但沒有運氣,因爲大多數分組似乎都發生在具有共同價值的屬性上。XSLT v1.0 - 如何分組不均勻的屬性?

更具體地說,我想要實現的目的是在pdf上打印,其中一行代表多個記錄,這些記錄具有屬性Ty(Att ty =「PC」)上具有值「PC」的Att元素的特定Ids。所有這些都應該與我現有的分組一起進行。

樣品我的XML代碼:

<Document> 
    <RecordDetails> 
     <Record> 
      <contact id="0001" title="Mr" forename="John" surname="Smith" ST='M'/> 
      <AggSet>     
       <Att Ty="Addr" Id="43 Menelaou Street" /> 
       <Att Ty="PC" Id="15230" /> 
       <Att Ty="Num" Id="2580052635" />    
      </AggSet> 
      <Charge Amount="3.000" PT="P" /> 
     </Record> 
     <Record> 
      <contact id="0001" title="Mr" forename="John" surname="Smith" ST='M'/> 
      <AggSet>     
       <Att Ty="Addr" Id="65 Dankan Street" /> 
       <Att Ty="PC" Id="15236" /> 
       <Att Ty="Num" Id="2580052635" />    
      </AggSet> 
      <Charge Amount="10.000" PT="P" /> 
     </Record> 
     <Record> 
      <contact id="0002" title="Dr" forename= "Amy" surname="Jones" ST='Y'/> 
      <AggSet>     
       <Att Ty="Addr" Id="28 Karman Street" /> 
       <Att Ty="PC" Id="15237" /> 
       <Att Ty="Num" Id="2584552635" />    
      </AggSet> 
      <Charge Amount="-2.000" PT="P" /> 
     </Record> 
     <Record>  
      ... 
     </Record> 
    </RecordDetails> 
</Document> 

所以例如用於記錄2,3,我想只打印1號線由於其職位代碼屬於同一區域的我,因爲泰=「個人電腦」意味着後,我想在更大面積的基礎上進行分組。

我使用的Apache FOP後續的xsl:

<xsl:key name="ct" match="Record[Charge/@PT='P']" use="@ST"/> 


<xsl:template match ="RecordDetails"> 
    <xsl:for-each select="Record[generate-id(.)=generate-id(key('ct',@ST)[1])]"> 
     <xsl:if test="@ST='M' and (./AggSet/Att[@Ty='PC']/@Id='15236' or ./AggSet/Att[@Ty='TZ']/@Id='15237' or ...) "> 
      <fo:table-row>       
        <xsl:apply-templates select="."/>        
      </fo:table-row> 
     </xsl:if> 
     <xsl:for-each select="key('ct',@ST)">      
      <xsl:choose>          
       <xsl:when test="@ST='M' and (./AggSet/Att[@Ty='PC']/@Id='15236' or ./AggSet/Att[@Ty='TZ']/@Id='15237' or ...) "> 
       </xsl:when>      
       <xsl:otherwise> 
        <fo:table-row> 
        <xsl:apply-templates select="."/> 
        </fo:table-row> 
       </xsl:otherwise> 
      </xsl:choose>    
     </xsl:for-each>        
    </xsl:for-each> 
</xsl:template> 

<xsl:template match="Record"> 
    <fo:table-cell> 
     <xsl:choose> 
      <xsl:when test="@ST='M' and (./AggSet/Att[@Ty='PC']/@Id='15236' or ./AggSet/Att[@Ty='TZ']/@Id='15237' or ...)"> 
       <fo:block text-align="center"> 
        <xsl:text>Greater area</xsl:text> 
       </fo:block> 
      </xsl:when> 
      <xsl:otherwise> 
       <fo:block text-align="center"> 
        <xsl:value-of select="./AggSet/Att[@Ty='PC']/@Id" /> 
       </fo:block> 
      </xsl:otherwise> 
     </xsl:choose> 
    </fo:table-cell> 
    <fo:table-cell> 
     <xsl:choose> 
      <xsl:when test="@ST='M' and (./AggSet/Att[@Ty='PC']/@Id='15236' or ./AggSet/Att[@Ty='TZ']/@Id='15237' or ...)"> 
       <fo:block text-align="center"> 
        <xsl:value-of select="sum(//Record[@ST='M' and (./AggSet/Att[@Ty='PC']/@Id='15236' or ./AggSet/Att[@Ty='TZ']/@Id='15237' or ...)]/contact/Charge/@Amount)" /> 
       </fo:block> 
      </xsl:when> 
      <xsl:otherwise> 
       <fo:block text-align="center"> 
        <xsl:value-of select="./Charge/@Amount" /> 
       </fo:block> 
      </xsl:otherwise> 
     </xsl:choose> 
    </fo:table-cell> 
</xsl:template> 

雖然我已經實現了這個邏輯在過去的實際我現有的分組內都有一個共同的屬性值的元素,上面的代碼沒有給我所有我想要的聚合線,我想知道是否有我的OR條件有問題,並由於某種原因它成爲假。

我錯過了什麼嗎? 任何幫助將不勝感激,

感謝

編輯: 作爲託默勒格指出了我的情況是什麼,我試圖做的是要手動組,這意味着裏面的代碼確實是硬編碼的條件。現在沒有通用的方法來爲我計算這些值。

+0

你能否更詳細地解釋*如何*不同的郵政編碼應該分組?組是手動定義還是可以計算?這應該是可配置的還是硬編碼的? – Tomalak

+0

非常準確的問題,請檢查我編輯的答案在頁面的底部。 – jeevana

回答

1

如何對這種做法:

<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:my="http://tempuri.org/config" 
    exclude-result-prefixes="my" 
> 
    <my:config> 
    <PC_group> 
     <item>15236</item> 
     <item>15237</item> 
    </PC_group> 
    <!-- more groups like this... --> 
    </my:config> 

    <!-- create a reference to our own config --> 
    <xsl:variable name="config" select="document('')/*/my:config" /> 
    <xsl:variable name="PC_group" select="$config/PC_group" /> 

    <xsl:template match="RecordDetails"> 
    <grouped_RecordDetails> 
     <xsl:apply-templates mode="group" select="Record[Charge/@PT='P']" /> 
    </grouped_RecordDetails> 
    </xsl:template> 

    <xsl:template match="Record" mode="group"> 
    <xsl:variable name="myPC" select="AggSet/Att[@Ty = 'PC']/@Id" /> 

    <!-- select all the PCs in this group --> 
    <xsl:variable name="groupPCs" select="$PC_group[item = $myPC]/item" /> 

    <!-- identify all other members of this group --> 
    <xsl:variable name="groupMembers" select=". | ../Record[ 
     Charge/@PT='P' and AggSet/Att[@Ty = 'PC']/@Id = $groupPCs 
    ]" /> 

    <!-- do the actual grouping, just like the Muenchian method... --> 
    <xsl:if test="generate-id() = generate-id($groupMembers[1])"> 

     <!-- 
     we are at the first Record in this group now 
     all the other group members are at $groupMembers 
     output whatever details you like here 
     --> 
     <xsl:copy-of select="." /> 

    </xsl:if> 
    </xsl:template> 

    <xsl:template match="text()[normalize-space() = '']" /> 

</xsl:stylesheet> 

樣本輸出

<grouped_RecordDetails> 
    <Record> 
    <contact id="0001" title="Mr" forename="John" surname="Smith" ST="M" /> 
    <AggSet> 
     <Att Ty="Addr" Id="43 Menelaou Street" /> 
     <Att Ty="PC" Id="15230" /> 
     <Att Ty="Num" Id="2580052635" /> 
    </AggSet> 
    <Charge Amount="3.000" PT="P" /> 
    </Record> 
    <Record> 
    <contact id="0001" title="Mr" forename="John" surname="Smith" ST="M" /> 
    <AggSet> 
     <Att Ty="Addr" Id="65 Dankan Street" /> 
     <Att Ty="PC" Id="15236" /> 
     <Att Ty="Num" Id="2580052635" /> 
    </AggSet> 
    <Charge Amount="10.000" PT="P" /> 
    </Record> 
</grouped_RecordDetails> 

編輯:當然,分組都可以在一個大的,凌亂的XPath表達式來完成,如果你喜歡:

<!-- identify all members of this group --> 
<xsl:variable name="groupMembers" select=" 
    . | ../Record[ 
    Charge/@PT = 'P' 
    and AggSet/Att[@Ty = 'PC']/@Id = $PC_group[ 
      item = current()/AggSet/Att[@Ty = 'PC']/@Id 
     ]/item 
    ] 
" /> 

Splittin把它變成幾個變量使得它更容易遵循。