我看过Muenchian Grouping - group within a node, not within the entire document,但对我来说不太合适。 Muenchian方法本身并不适合我。
我也查看了XSLT 1.0: grouping and removing duplicate,但无法完全遵循它。
我有以下XML:
<?xml version="1.0" encoding="UTF-8"?>
<MT_MATERIALDATA>
<items item="475053">
<Recordset>
<CodeBusinessUnit>99</CodeBusinessUnit>
<PriceValue>250</PriceValue>
</Recordset>
<Recordset>
<CodeBusinessUnit>1</CodeBusinessUnit>
<PriceValue>250</PriceValue>
</Recordset>
</items>
<items item="475054">
<Recordset>
<CodeBusinessUnit>1</CodeBusinessUnit>
<PriceValue>255.34</PriceValue>
</Recordset>
<Recordset>
<CodeBusinessUnit>10</CodeBusinessUnit>
<PriceValue>299</PriceValue>
</Recordset>
</items>
</MT_MATERIALDATA>
结果应如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<MT_MATERIALDATA>
<Mi item="475053">
<PriceList>
<Prices>
<Price Value="250"/>
<PriceConfig>
<Stores>99,1</Stores>
</PriceConfig>
</Prices>
</PriceList>
</Mi>
<Mi item="475054">
<PriceList>
<Prices>
<Price Value="255.34"/>
<PriceConfig>
<Stores>1</Stores>
</PriceConfig>
</Prices>
<Prices>
<Price Value="299"/>
<PriceConfig>
<Stores>10</Stores>
</PriceConfig>
</Prices>
</PriceList>
</Mi>
</MT_MATERIALDATA>
因此匹配<PriceValue>
元素
在<Recordset>
中,所有相应的<CodeBusinessUnits>
都需要列在<Stores>
中。
如果没有,则需要创建额外的<Prices>
节点。
我已经尝试了几个小时,但是Store-number总是重复,或者即使PriceValue相同也不会聚合。我感谢任何帮助,我不知道该怎么办。谢谢你的帮助!
祝你好运, 彼得
答案 0 :(得分:1)
我认为以下问题解决了这个问题,至少对于分组来说是这样的:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="k1" match="items/Recordset" use="concat(generate-id(..), '|', PriceValue)"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="items">
<Mi item="{@item}">
<PriceList>
<xsl:apply-templates select="Recordset[generate-id() = generate-id(key('k1', concat(generate-id(..), '|', PriceValue))[1])]"/>
</PriceList>
</Mi>
</xsl:template>
<xsl:template match="Recordset">
<Prices>
<Price Value="{PriceValue}"/>
<PriceConfig>
<Stores>
<xsl:apply-templates select="key('k1', concat(generate-id(..), '|', PriceValue))/CodeBusinessUnit"/>
</Stores>
</PriceConfig>
</Prices>
</xsl:template>
<xsl:template match="CodeBusinessUnit">
<xsl:if test="position() > 1">,</xsl:if>
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
此转化:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kPriceByValAndItem" match="PriceValue"
use="concat(../../@item, '|', .)"/>
<xsl:template match="/*">
<MT_MATERIALDATA>
<xsl:apply-templates/>
</MT_MATERIALDATA>
</xsl:template>
<xsl:template match="items">
<MI item="{@item}">
<PriceList>
<xsl:for-each select=
"*/PriceValue
[generate-id()
=
generate-id(key('kPriceByValAndItem',
concat(../../@item, '|', .)
)[1]
)
]
">
<Prices>
<Price Value="{.}"/>
<PriceConfig>
<Stores>
<xsl:for-each select=
"key('kPriceByValAndItem',
concat(../../@item, '|', .)
)">
<xsl:value-of select="../CodeBusinessUnit"/>
<xsl:if test="not(position()=last())">,</xsl:if>
</xsl:for-each>
</Stores>
</PriceConfig>
</Prices>
</xsl:for-each>
</PriceList>
</MI>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档时:
<MT_MATERIALDATA>
<items item="475053">
<Recordset>
<CodeBusinessUnit>99</CodeBusinessUnit>
<PriceValue>250</PriceValue>
</Recordset>
<Recordset>
<CodeBusinessUnit>1</CodeBusinessUnit>
<PriceValue>250</PriceValue>
</Recordset>
</items>
<items item="475054">
<Recordset>
<CodeBusinessUnit>1</CodeBusinessUnit>
<PriceValue>255.34</PriceValue>
</Recordset>
<Recordset>
<CodeBusinessUnit>10</CodeBusinessUnit>
<PriceValue>299</PriceValue>
</Recordset>
</items>
</MT_MATERIALDATA>
会产生想要的正确结果:
<MT_MATERIALDATA>
<MI item="475053">
<PriceList>
<Prices>
<Price Value="250"/>
<PriceConfig>
<Stores>99,1</Stores>
</PriceConfig>
</Prices>
</PriceList>
</MI>
<MI item="475054">
<PriceList>
<Prices>
<Price Value="255.34"/>
<PriceConfig>
<Stores>1</Stores>
</PriceConfig>
</Prices>
<Prices>
<Price Value="299"/>
<PriceConfig>
<Stores>10</Stores>
</PriceConfig>
</Prices>
</PriceList>
</MI>
</MT_MATERIALDATA>
答案 2 :(得分:1)
我还要发布一个样式表,因为每个人都这样做:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="kBUnitByItem-Price"
match="CodeBusinessUnit"
use="concat(../../@item, '++', ../PriceValue)"/>
<xsl:template match="/">
<MT_MATERIALDATA>
<xsl:apply-templates/>
</MT_MATERIALDATA>
</xsl:template>
<xsl:template match="items">
<MI item="{@item}">
<PriceList>
<xsl:apply-templates/>
</PriceList>
</MI>
</xsl:template>
<xsl:template match="CodeBusinessUnit[
count(.|key('kBUnitByItem-Price',
concat(../../@item,'++',../PriceValue)
)[1]
) = 1
]">
<Prices>
<Price Value="{../PriceValue}"/>
<PriceConfig>
<Stores>
<xsl:apply-templates
select="key('kBUnitByItem-Price',
concat(../../@item,'++',../PriceValue))"
mode="sequence"/>
</Stores>
</PriceConfig>
</Prices>
</xsl:template>
<xsl:template match="text()"/>
<xsl:template match="node()" mode="sequence">
<xsl:if test="position()!=1">,</xsl:if>
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
注意:按商品和价格对商店进行分组。比推送风格多一点拉(这是因为没有重复的@item。)
输出:
<MT_MATERIALDATA>
<MI item="475053">
<PriceList>
<Prices>
<Price Value="250" />
<PriceConfig>
<Stores>99,1</Stores>
</PriceConfig>
</Prices>
</PriceList>
</MI>
<MI item="475054">
<PriceList>
<Prices>
<Price Value="255.34" />
<PriceConfig>
<Stores>1</Stores>
</PriceConfig>
</Prices>
<Prices>
<Price Value="299" />
<PriceConfig>
<Stores>10</Stores>
</PriceConfig>
</Prices>
</PriceList>
</MI>
</MT_MATERIALDATA>
我认为我们涵盖了所有变化:键值,推拉,序列分隔符条件。