xslt 1.0 使用复合键分组(在不同级别)
Posted
技术标签:
【中文标题】xslt 1.0 使用复合键分组(在不同级别)【英文标题】:xslt 1.0 grouping with compound keys (at different levels) 【发布时间】: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 创建按注册和付款方式分组的摘要记录?
【问题讨论】:
【参考方案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>
解释:
正确使用:
Muenchian Grouping method。
AVT s(属性值模板)。
【讨论】:
复合分组键的使用非常有用!以上是关于xslt 1.0 使用复合键分组(在不同级别)的主要内容,如果未能解决你的问题,请参考以下文章