是的,这是另一个XSLT分组/重复问题,但我无法找到任何可以成功应用于我的情况的答案。
这是原始的XML:
<data jsxid="jsxroot">
<record jsxid="10" groupNum="1319" item="q123" total="1"/>
<record jsxid="20" groupNum="1319" item="w123" total="1"/>
<record jsxid="30" groupNum="1319" item="" total="0"/>
<record jsxid="40" groupNum="1322" item="z123" total="1"/>
<record jsxid="50" groupNum="1322" item="x123" total="1"/>
<record jsxid="60" groupNum="1322" item="c123" total="1"/>
<record jsxid="70" groupNum="1322" item="" total="0"/>
<record jsxid="80" groupNum="1323" item="x123" total="1"/>
<record jsxid="90" groupNum="1323" item="c123" total="1"/>
<record jsxid="100" groupNum="1323" item="z123" total="1"/>
<record jsxid="110" groupNum="1323" item="" total="0"/>
</data>
首先,我需要按属性分组&#34; groupNum&#34;并包装在父元素jsxid中,该元素随每个组递增,因此输出如下所示:
<data jsxid="jsxroot">
<record jsxid="1">
<record jsxid="10" groupNum="1319" item="q123" total="1"/>
<record jsxid="20" groupNum="1319" item="w123" total="1"/>
<record jsxid="30" groupNum="1319" item="" total="0"/>
</record>
<record jsxid="2">
<record jsxid="40" groupNum="1322" item="z123" total="1"/>
<record jsxid="50" groupNum="1322" item="x123" total="1"/>
<record jsxid="60" groupNum="1322" item="c123" total="1"/>
<record jsxid="70" groupNum="1322" item="" total="0"/>
</record>
<record jsxid="3">
<record jsxid="80" groupNum="1323" item="x123" total="1"/>
<record jsxid="90" groupNum="1323" item="c123" total="1"/>
<record jsxid="100" groupNum="1323" item="z123" total="1"/>
<record jsxid="110" groupNum="1323" item="" total="0"/>
</record>
</data>
我能够用这个样式表来实现这个目标:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:key name="groupNum" match="data/*" use="@groupNum" />
<xsl:template match="data">
<data>
<xsl:apply-templates select="*[generate-id(.)=generate-id(key('groupNum',@groupNum)[1])]"/>
</data>
</xsl:template>
<xsl:template match="*">
<record jsxid="{position()}" >
<xsl:copy-of select="key('groupNum', @groupNum)" />
</record>
</xsl:template>
</xsl:stylesheet>
现在我需要删除任何包含与另一个分组完全相同的项目的分组,其中记录总数=&#34; 1&#34;。如果您查看上面的jsxid = 2和jsxid = 3的分组,您会看到它们都包含以下项属性,但顺序不同:
item="x123"
item="c123"
item="z123"
所以我想删除整个jsxid = 3分组并让最终输出看起来像这样:
<data jsxid="jsxroot">
<record jsxid="1">
<record jsxid="1" groupNum="1319" item="q123" total="1"/>
<record jsxid="2" groupNum="1319" item="w123" total="1"/>
<record jsxid="3" groupNum="1319" item="" total="0"/>
</record>
<record jsxid="2">
<record jsxid="4" groupNum="1322" item="z123" total="1"/>
<record jsxid="5" groupNum="1322" item="x123" total="1"/>
<record jsxid="6" groupNum="1322" item="c123" total="1"/>
<record jsxid="7" groupNum="1322" item="" total="0"/>
</record>
</data>
编辑:如果我想将新属性添加为&#34;分组标识符,该怎么办呢?&#34;而不是删除重复的分组。我称它为&#34; groupType&#34;所以最后两个分组相同的上述情况的输出,它们将具有相同的grouptype:
<data jsxid="jsxroot">
<record jsxid="1">
<record jsxid="10" groupNum="1319" item="q123" groupType = "type1" total="1"/>
<record jsxid="20" groupNum="1319" item="w123" groupType = "type1" total="1"/>
<record jsxid="30" groupNum="1319" item="" groupType = "type1" total="0"/>
</record>
<record jsxid="2">
<record jsxid="40" groupNum="1322" item="z123" groupType = "type2" total="1"/>
<record jsxid="50" groupNum="1322" item="x123" groupType = "type2" total="1"/>
<record jsxid="60" groupNum="1322" item="c123" groupType = "type2" total="1"/>
<record jsxid="70" groupNum="1322" item="" groupType = "type2" total="0"/>
</record>
<record jsxid="3">
<record jsxid="80" groupNum="1323" item="x123" groupType = "type2" total="1"/>
<record jsxid="90" groupNum="1323" item="c123" groupType = "type2" total="1"/>
<record jsxid="100" groupNum="1323" item="z123" groupType = "type2" total="1"/>
<record jsxid="110" groupNum="1323" item="" groupType = "type2" total="0"/>
</record>
</data>
非常感谢任何帮助。
答案 0 :(得分:0)
这并不简单,所以请坐在座位上:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:variable name="root" select="/" />
<xsl:key name="rec-by-group" match="record" use="@groupNum" />
<xsl:key name="group-by-items" match="group" use="@items" />
<xsl:template match="/">
<!-- first pass -->
<xsl:variable name="groups">
<!-- for each unique groupNum ... -->
<xsl:for-each select="data/record[count(. | key('rec-by-group', @groupNum)[1]) = 1]">
<xsl:variable name="groupNum" select="@groupNum" />
<!-- ... create a group ... -->
<group groupNum="{$groupNum}">
<!-- ... and concatenate all its items - in known order(!) - into a single attribute. -->
<xsl:attribute name="items">
<!-- switch context back to document in order to use key -->
<xsl:for-each select="$root">
<xsl:for-each select="key('rec-by-group', $groupNum)[@total=1]">
<xsl:sort select="@item" data-type="text" order="ascending"/>
<xsl:value-of select="@item"/>
<xsl:text>|</xsl:text>
</xsl:for-each>
</xsl:for-each>
</xsl:attribute>
</group>
</xsl:for-each>
</xsl:variable>
<!-- final pass -->
<data jsxid="jsxroot">
<!-- for each unique group (unique by its @items attribute) ... -->
<xsl:for-each select="exsl:node-set($groups)/group[count(. | key('group-by-items', @items)[1]) = 1]">
<!-- ... create a wrapper record ... -->
<record jsxid="{position()}">
<xsl:variable name="groupNum" select="@groupNum" />
<!-- switch context back to document in order to use key -->
<xsl:for-each select="$root">
<!-- ... and list the records in this group. -->
<xsl:for-each select="key('rec-by-group', $groupNum)">
<record>
<xsl:attribute name="jsxid">
<xsl:number/>
</xsl:attribute>
<xsl:copy-of select="@groupNum | @item | @total"/>
</record>
</xsl:for-each>
</xsl:for-each>
</record>
</xsl:for-each>
</data>
</xsl:template>
</xsl:stylesheet>
响应您的修改:
如果您可以使用groupType
作为任意(虽然是唯一的)号码,您可以将“最终通行证”部分更改为:
<!-- final pass -->
<data jsxid="jsxroot">
<!-- for each group ... -->
<xsl:for-each select="exsl:node-set($groups)/group">
<!-- ... create a wrapper record ... -->
<record jsxid="{position()}">
<xsl:variable name="groupNum" select="@groupNum" />
<xsl:variable name="groupType" select="key('group-by-items', @items)[1]/@groupNum" />
<!-- switch context back to document in order to use key -->
<xsl:for-each select="$root">
<!-- ... and list the records in this group. -->
<xsl:for-each select="key('rec-by-group', $groupNum)">
<record groupType="{$groupType}">
<xsl:attribute name="jsxid">
<xsl:number/>
</xsl:attribute>
<xsl:copy-of select="@groupNum | @item | @total"/>
</record>
</xsl:for-each>
</xsl:for-each>
</record>
</xsl:for-each>
</data>
使用您的输入示例,这将返回:
<?xml version="1.0" encoding="UTF-8"?>
<data jsxid="jsxroot">
<record jsxid="1">
<record groupType="1319" jsxid="1" groupNum="1319" item="q123" total="1"/>
<record groupType="1319" jsxid="2" groupNum="1319" item="w123" total="1"/>
<record groupType="1319" jsxid="3" groupNum="1319" item="" total="0"/>
</record>
<record jsxid="2">
<record groupType="1322" jsxid="4" groupNum="1322" item="z123" total="1"/>
<record groupType="1322" jsxid="5" groupNum="1322" item="x123" total="1"/>
<record groupType="1322" jsxid="6" groupNum="1322" item="c123" total="1"/>
<record groupType="1322" jsxid="7" groupNum="1322" item="" total="0"/>
</record>
<record jsxid="3">
<record groupType="1322" jsxid="8" groupNum="1323" item="x123" total="1"/>
<record groupType="1322" jsxid="9" groupNum="1323" item="c123" total="1"/>
<record groupType="1322" jsxid="10" groupNum="1323" item="z123" total="1"/>
<record groupType="1322" jsxid="11" groupNum="1323" item="" total="0"/>
</record>
</data>
如您所见,它使用当前类型的第一组groupNum
作为groupType
值。或者,您也可以使用该组的自动生成ID:
<xsl:variable name="groupType" select="generate-id(key('group-by-items', @items)[1])" />.
答案 1 :(得分:-1)
要仅复制第一个实例,在生成每个项目时,请使用count(preceding-sibling :: * [])= 0将其括在条件中。
<xsl:template match="record">
<xsl:variable name="item" select="item"/>
<record jsxid="{position()}" >
<xsl:if test="count (preceding-sibling::*[item=$item])=0">
<xsl:copy-of select="key('groupNum', @groupNum)" />
</xsl:if>
</record>
</xsl:template>