使用下面的XML,我需要弄清楚哪个人在每个站点工作的时间更长。例如,在下面的XML中,人1在站点1中工作8小时但是人2工作仅6小时。因此,结果应包含转换后的XML中的person 1和site 1。如果小时数相等,请选择第一个人。
编辑:我希望使用XSLT 1.0实现它。
<root>
<WorkSite Person="P1" Site="S1">
<Hours>8</Hours>
</WorkSite>
<WorkSite Person="P1" Site="S2">
<Hours>2</Hours>
</WorkSite>
<WorkSite Person="P1" Site="S3">
<Hours>9</Hours>
</WorkSite>
<WorkSite Person="P2" Site="S1">
<Hours>6</Hours>
</WorkSite>
<WorkSite Person="P2" Site="S2">
<Hours>10</Hours>
</WorkSite>
<WorkSite Person="P2" Site="S3">
<Hours>2</Hours>
</WorkSite>
</root>
XSLT转换结果应该是这样的:
<root>
<WorkSite Person="P1" Site="S1"/>
<WorkSite Person="P2" Site="S2"/>
<WorkSite Person="P1" Site="S3"/>
</root>
答案 0 :(得分:7)
此XSLT 1.0转换:
<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="kSiteByName" match="@Site" use="."/>
<xsl:key name="kWorksiteBySite"
match="WorkSite" use="@Site"/>
<xsl:variable name="vSites" select=
"/*/*/@Site[generate-id()
=
generate-id(key('kSiteByName',.)[1])
]"
/>
<xsl:template match="/">
<root>
<xsl:for-each select="$vSites">
<xsl:for-each select="key('kWorksiteBySite', .)">
<xsl:sort select="Hours" data-type="number"
order="descending"/>
<xsl:if test="position()=1">
<xsl:copy>
<xsl:copy-of select="@*"/>
</xsl:copy>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档:
<root>
<WorkSite Person="P1" Site="S1">
<Hours>8</Hours>
</WorkSite>
<WorkSite Person="P1" Site="S2">
<Hours>2</Hours>
</WorkSite>
<WorkSite Person="P1" Site="S3">
<Hours>9</Hours>
</WorkSite>
<WorkSite Person="P2" Site="S1">
<Hours>6</Hours>
</WorkSite>
<WorkSite Person="P2" Site="S2">
<Hours>10</Hours>
</WorkSite>
<WorkSite Person="P2" Site="S3">
<Hours>2</Hours>
</WorkSite>
</root>
生成想要的正确结果:
<root>
<WorkSite Person="P1" Site="S1"/>
<WorkSite Person="P2" Site="S2"/>
<WorkSite Person="P1" Site="S3"/>
</root>
请注意:
使用Muenchian方法进行分组以查找所有不同的Site
值。
通过按降序排序找到最大值的方式,并从排序的节点列表中获取第一个结果。
答案 1 :(得分:2)
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<root>
<xsl:for-each-group select="*/WorkSite" group-by="@Site">
<WorkSite Person="{(current-group()[Hours = max(current-group()/Hours)])[1]/@Person}" Site="{current-grouping-key()}" />
</xsl:for-each-group>
</root>
</xsl:template>
</xsl:stylesheet>
答案 2 :(得分:0)
XSLT 1.0解决方案。这个样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="BySite" match="WorkSite" use="@Site"/>
<xsl:template match="root">
<root>
<xsl:for-each select="/*/WorkSite[count(.|key('BySite',@Site)[1])=1]">
<WorkSite Person="{key('BySite',@Site)
[not(key('BySite',@Site)/Hours
> Hours)]/@Person}"
Site="{@Site}" />
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
输出:
<root>
<WorkSite Person="P1" Site="S1" />
<WorkSite Person="P2" Site="S2" />
<WorkSite Person="P1" Site="S3" />
</root>