【问题标题】:xslt 1.0 grouping with compound keys (at different levels)xslt 1.0 使用复合键分组(在不同级别)
【发布时间】:2013-04-17 08:48:02
【问题描述】:

我有一个转换,我试图记录一组扁平化交易详细信息,并在文件末尾提供按投标类型和登记号分组的总数的总和。
记录一组单独的交易细节是很容易的部分,我工作得很好,但我在总结部分苦苦挣扎。

问题是我不知道有什么或多少个不同的寄存器号,或者有什么或有多少投标类型(因此在 xslt 中明确列出带有静态过滤器字符串的摘要是不行的) ,所以某种分组似乎是有序的。

再来一个扳手——我被 XSLT 1.0 卡住了……

我尝试弄乱 muenchian 分组,但在复合键要求(注册生活在与付款方式不同的级别)和我对 muenchian 方法和键如何工作的有限理解之间我不能似乎让它工作了,但我认为它仍然可能是需要的技巧......

有什么建议可以让我用 muenchia 神奇地让它工作吗?

这是一个示例源文档:

<s0:SalesCollection xmlns:s0="http://mySourceSchema">
  <s0:Sale transactionnumber="1" register="1">
    <s0:Tender amount="1.11" paymentmethod="visa" />
    <s0:Tender amount="2.22" paymentmethod="mastercard" />
  </s0:Sale>
  <s0:Sale transactionnumber="2" register="1">
    <s0:Tender amount="5.55" paymentmethod="discover" />
    <s0:Tender amount="4.44" paymentmethod="visa" />
  </s0:Sale>
  <s0:Sale transactionnumber="1" register="2">
    <s0:Tender amount="9.99" paymentmethod="amex" />
    <s0:Tender amount="8.88" paymentmethod="visa" />
  </s0:Sale>
</s0:SalesCollection>

这就是我想要的(同样,我的记录 [@type='detail'] 记录已经在工作):

<ns0:root xmlns:ns0="http://myDestinationSchema">
  <ns0:record type="detail" transactionnumber="1" register="1" amount="1.11" paymentmethod="visa" />
  <ns0:record type="detail" transactionnumber="1" register="1" amount="2.22" paymentmethod="mastercard" />
  <ns0:record type="detail" transactionnumber="2" register="1" amount="5.55" paymentmethod="discover" />
  <ns0:record type="detail" transactionnumber="2" register="1" amount="4.44" paymentmethod="visa" />
  <ns0:record type="detail" transactionnumber="1" register="2" amount="9.99" paymentmethod="amex" />
  <ns0:record type="detail" transactionnumber="1" register="2" amount="8.88" paymentmethod="visa" />
  <ns0:record type="summary" register="1" amount="5.55" paymentmethod="visa" />
  <ns0:record type="summary" register="1" amount="2.22" paymentmethod="mastercard" />
  <ns0:record type="summary" register="1" amount="5.55" paymentmethod="discover" />
  <ns0:record type="summary" register="2" amount="9.99" paymentmethod="amex" />
  <ns0:record type="summary" register="2" amount="8.88" paymentmethod="visa" />
</ns0:root>

那么如何使用 xslt 1.0 创建按注册和付款方式分组的摘要记录?

【问题讨论】:

    标签: xml xslt muenchian-grouping


    【解决方案1】:

    当这个 XSLT:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:ns0="http://myDestinationSchema"
      xmlns:s0="http://mySourceSchema"
      exclude-result-prefixes="s0"
      version="1.0">
      <xsl:output omit-xml-declaration="yes" indent="yes"/>
      <xsl:strip-space elements="*"/>
    
      <xsl:key
        name="kTenderByRegisterAndMethod"
        match="s0:Tender"
        use="concat(parent::*/@register, '+', @paymentmethod)"/>
    
      <xsl:template match="@*|node()">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="/*">
        <ns0:root>
          <xsl:apply-templates select="*/s0:Tender"/>
          <xsl:apply-templates 
            select="*/s0:Tender[generate-id() = 
                                generate-id(key(
                                  'kTenderByRegisterAndMethod',
                                  concat(parent::*/@register,
                                         '+',
                                         @paymentmethod))[1])]"
            mode="summary"/>
        </ns0:root>
      </xsl:template>
    
      <xsl:template match="s0:Tender">
        <ns0:record type="detail">
          <xsl:apply-templates select="parent::*/@*|@*"/>
        </ns0:record>
      </xsl:template>
    
      <xsl:template match="s0:Tender" mode="summary">
        <ns0:record type="summary" register="{parent::*/@register}">
          <xsl:attribute name="amount">
            <xsl:value-of
              select="sum(
                        key('kTenderByRegisterAndMethod',
                            concat(parent::*/@register,
                            '+', @paymentmethod))/@amount)"/>
          </xsl:attribute>
          <xsl:apply-templates select="@*[not(name() = 'amount')]"/>
        </ns0:record>
      </xsl:template>
    </xsl:stylesheet>
    

    ...应用于原始 XML:

    <s0:SalesCollection xmlns:s0="http://mySourceSchema">
      <s0:Sale transactionnumber="1" register="1">
        <s0:Tender amount="1.11" paymentmethod="visa"/>
        <s0:Tender amount="2.22" paymentmethod="mastercard"/>
      </s0:Sale>
      <s0:Sale transactionnumber="2" register="1">
        <s0:Tender amount="5.55" paymentmethod="discover"/>
        <s0:Tender amount="4.44" paymentmethod="visa"/>
      </s0:Sale>
      <s0:Sale transactionnumber="1" register="2">
        <s0:Tender amount="9.99" paymentmethod="amex"/>
        <s0:Tender amount="8.88" paymentmethod="visa"/>
      </s0:Sale>
    </s0:SalesCollection>
    

    ...产生想要的结果:

    <ns0:root xmlns:ns0="http://myDestinationSchema">
      <ns0:record type="detail" transactionnumber="1" register="1" amount="1.11" paymentmethod="visa"/>
      <ns0:record type="detail" transactionnumber="1" register="1" amount="2.22" paymentmethod="mastercard"/>
      <ns0:record type="detail" transactionnumber="2" register="1" amount="5.55" paymentmethod="discover"/>
      <ns0:record type="detail" transactionnumber="2" register="1" amount="4.44" paymentmethod="visa"/>
      <ns0:record type="detail" transactionnumber="1" register="2" amount="9.99" paymentmethod="amex"/>
      <ns0:record type="detail" transactionnumber="1" register="2" amount="8.88" paymentmethod="visa"/>
      <ns0:record type="summary" register="1" amount="5.55" paymentmethod="visa"/>
      <ns0:record type="summary" register="1" amount="2.22" paymentmethod="mastercard"/>
      <ns0:record type="summary" register="1" amount="5.55" paymentmethod="discover"/>
      <ns0:record type="summary" register="2" amount="9.99" paymentmethod="amex"/>
      <ns0:record type="summary" register="2" amount="8.88" paymentmethod="visa"/>
    </ns0:root>
    

    说明

    您在检查 Muenchian Grouping 时走在了正确的轨道上。请注意我使用的组合键,它通过连接其父元素的 @register 值、“+”号(为了方便并确保连接永远不会被破坏)和它们的 @paymentmethod 值来匹配 s0:Tender 元素。

    坚持使用 Muenchian 分组,即使它不是最容易立即理解的概念。我自己通过查看Muenchian Grouping-related questions on SO 并尝试回答它们来学习;随着时间的推移,我开始明白了。

    【讨论】:

      【解决方案2】:

      这种转变

      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
       xmlns:s0="http://mySourceSchema"
       xmlns:ns0="http://myDestinationSchema" exclude-result-prefixes="s0">
       <xsl:output omit-xml-declaration="yes" indent="yes"/>
       <xsl:strip-space elements="*"/>
      
       <xsl:key name="kTendByTypeAndReg" match="s0:Tender"
        use="concat(../@register, '#', @paymentmethod)"/>
      
       <xsl:template match="/*">
        <ns0:root xmlns:ns0="http://myDestinationSchema">
         <xsl:apply-templates select="*/*"/>
         <xsl:apply-templates mode="group" select=
         "*/*[generate-id()
             =generate-id(key('kTendByTypeAndReg',
                              concat(../@register, '#', @paymentmethod))[1]
                              )
             ]"/>
        </ns0:root>
       </xsl:template>
      
       <xsl:template match="s0:Tender">
         <ns0:record type="detail" transactionnumber="{../@transactionnumber}"
             register="{../@register}" amount="{@amount}" paymentmethod="{@paymentmethod}" />
       </xsl:template>
      
       <xsl:template match="*" mode="group">
          <ns0:record type="summary" register="{../@register}" paymentmethod="{@paymentmethod}"
        amount="{sum(key('kTendByTypeAndReg',concat(../@register,'#',@paymentmethod))
                         /@amount)}"/>
       </xsl:template>
      </xsl:stylesheet>
      

      应用于提供的 XML 文档时:

      <s0:SalesCollection xmlns:s0="http://mySourceSchema">
        <s0:Sale transactionnumber="1" register="1">
          <s0:Tender amount="1.11" paymentmethod="visa" />
          <s0:Tender amount="2.22" paymentmethod="mastercard" />
        </s0:Sale>
        <s0:Sale transactionnumber="2" register="1">
          <s0:Tender amount="5.55" paymentmethod="discover" />
          <s0:Tender amount="4.44" paymentmethod="visa" />
        </s0:Sale>
        <s0:Sale transactionnumber="1" register="2">
          <s0:Tender amount="9.99" paymentmethod="amex" />
          <s0:Tender amount="8.88" paymentmethod="visa" />
        </s0:Sale>
      </s0:SalesCollection>
      

      产生想要的结果

      <ns0:root xmlns:ns0="http://myDestinationSchema">
          <ns0:record type="detail" transactionnumber="1" register="1" amount="1.11" paymentmethod="visa"/>
          <ns0:record type="detail" transactionnumber="1" register="1" amount="2.22" paymentmethod="mastercard"/>
          <ns0:record type="detail" transactionnumber="2" register="1" amount="5.55" paymentmethod="discover"/>
          <ns0:record type="detail" transactionnumber="2" register="1" amount="4.44" paymentmethod="visa"/>
          <ns0:record type="detail" transactionnumber="1" register="2" amount="9.99" paymentmethod="amex"/>
          <ns0:record type="detail" transactionnumber="1" register="2" amount="8.88" paymentmethod="visa"/>
          <ns0:record type="summary" register="1" paymentmethod="visa" amount="5.55"/>
          <ns0:record type="summary" register="1" paymentmethod="mastercard" amount="2.22"/>
          <ns0:record type="summary" register="1" paymentmethod="discover" amount="5.55"/>
          <ns0:record type="summary" register="2" paymentmethod="amex" amount="9.99"/>
          <ns0:record type="summary" register="2" paymentmethod="visa" amount="8.88"/>
      </ns0:root>
      

      解释

      正确使用:

      1. Muenchian Grouping method

      2. AVT s(属性值模板)。

      【讨论】:

      • 复合分组键的使用非常有用!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-20
      • 2011-10-27
      • 2015-03-20
      • 1970-01-01
      • 1970-01-01
      • 2018-03-28
      相关资源
      最近更新 更多