【问题标题】:How to sort an XMl using XSLT 1.0?如何使用 XSLT 1.0 对 XML 进行排序?
【发布时间】:2010-08-15 16:10:23
【问题描述】:

我正在寻找一个 XSL 来按一个节点对 XML 进行排序和分组,并按另一个节点求和。我将不得不使用 XSLT 1.0。

这是我的 XML。 排序后,我需要一个新的 XML 排序并按<TransCode> 分组,并且所有<TransAmt> 应该为每个组求和。我正在为这项任务寻找 XSL。任何帮助表示赞赏。对新 XML 进行排序后,应该只有三个节点按 <TransCode> 的升序排序。所有<TransAmt> 必须加在一起。

这是我的 XML:

<Transactions>
 <Transaction>
  <TransCode>0008</TransCode>
  <TransType>Purchase</TransType>
  <TransAmt>12.30</TransAmt>
 </Transaction>

 <Transaction>
  <TransCode>0002</TransCode>
  <TransType>Cash</TransType>
  <TransAmt>26.00</TransAmt>
 </Transaction>

 <Transaction>
  <TransCode>0008</TransCode>
  <TransType>Purchase</TransType>
  <TransAmt>25.00</TransAmt>
 </Transaction>

 <Transaction>
  <TransCode>0015</TransCode>
  <TransType>FinanceCharge</TransType>
  <TransAmt>25.00</TransAmt>
 </Transaction>

 <Transaction>
  <TransCode>0002</TransCode>
  <TransType>Cash</TransType>
  <TransAmt>50.00</TransAmt>
 </Transaction>

 <Transaction>
  <TransCode>0008</TransCode>
  <TransType>Purchase</TransType>
  <TransAmt>40.00</TransAmt>
 </Transaction>
</Transactions>

【问题讨论】:

  • 您是否要求我们为您编写 XSL?也许您可以发布您提出的 XSL 并告诉我们您遇到的问题和问题?您想要的输出文档样本也将有助于回答问题。
  • 好问题 (+1)。有关关键思想的完整有效解决方案和解释,请参阅我的答案。 :)

标签: xml xslt sorting using


【解决方案1】:

这种转变

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"  />

 <xsl:key name="kTransByCode"
     match="Transaction" use="TransCode"/>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="/Transactions">
  <Transactions>
   <xsl:apply-templates select=
    "Transaction[generate-id()
                =
                 generate-id(key('kTransByCode',
                                  TransCode
                                  )[1]
                             )
                 ]
    ">
     <xsl:sort select="TransCode" data-type="number"/>
    </xsl:apply-templates>
  </Transactions>
 </xsl:template>

 <xsl:template match="TransAmt">
  <TransAmt>
    <xsl:value-of select=
    "sum(key('kTransByCode',../TransCode)/TransAmt)"/>
  </TransAmt>
 </xsl:template>
</xsl:stylesheet>

应用于提供的 XML 文档时

<Transactions>
 <Transaction>
  <TransCode>0008</TransCode>
  <TransType>Purchase</TransType>
  <TransAmt>12.30</TransAmt>
 </Transaction>

 <Transaction>
  <TransCode>0002</TransCode>
  <TransType>Cash</TransType>
  <TransAmt>26.00</TransAmt>
 </Transaction>

 <Transaction>
  <TransCode>0008</TransCode>
  <TransType>Purchase</TransType>
  <TransAmt>25.00</TransAmt>
 </Transaction>

 <Transaction>
  <TransCode>0015</TransCode>
  <TransType>FinanceCharge</TransType>
  <TransAmt>25.00</TransAmt>
 </Transaction>

 <Transaction>
  <TransCode>0002</TransCode>
  <TransType>Cash</TransType>
  <TransAmt>50.00</TransAmt>
 </Transaction>

 <Transaction>
  <TransCode>0008</TransCode>
  <TransType>Purchase</TransType>
  <TransAmt>40.00</TransAmt>
 </Transaction>
</Transactions>

产生想要的正确结果

<Transactions>
   <Transaction>
      <TransCode>0002</TransCode>
      <TransType>Cash</TransType>
      <TransAmt>76</TransAmt>
   </Transaction>
   <Transaction>
      <TransCode>0008</TransCode>
      <TransType>Purchase</TransType>
      <TransAmt>77.3</TransAmt>
   </Transaction>
   <Transaction>
      <TransCode>0015</TransCode>
      <TransType>FinanceCharge</TransType>
      <TransAmt>25</TransAmt>
   </Transaction>
</Transactions>

请注意

  1. 使用 Muenchian 分组方法

  2. 使用密钥可以轻松高效地求和每个转码。

  3. 身份规则用于按原样复制大多数元素,并被与输出中不同的元素匹配的模板覆盖。

【讨论】:

  • +1 好答案!但是,我认为如果您匹配“同类中的第一个”TransactionTransAmt/text(),它可能会不那么冗长。我这么说是因为有些人抱怨 XSLT 过于冗长,你知道的。
【解决方案2】:

XSL 内置了对 &lt;xsl:sort&gt; 元素的排序,并使用 XPath sum 函数求和。

XSLT 1.0 支持两者。

您在使用这些工具时遇到了什么问题?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-16
    • 1970-01-01
    • 2021-10-17
    • 1970-01-01
    • 1970-01-01
    • 2020-09-11
    • 2010-10-09
    相关资源
    最近更新 更多