2014-01-22 35 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把它变成几个变量使得它更容易遵循。