问题
I want to group the following XML:
<DataSet>
<FirstNode>
<UniqueKey>111</UniqueKey>
<OtherKey>552</OtherKey>
</FirstNode>
<FirstNode>
<UniqueKey>123</UniqueKey>
<OtherKey>552</OtherKey>
</FirstNode>
<FirstNode>
<UniqueKey>154</UniqueKey>
<OtherKey>553</OtherKey>
</FirstNode>
<SecondNode>
<FirstNodeKey>111</FirstNodeKey>
</SecondNode>
<SecondNode>
<FirstNodeKey>123></FirstNodeKey>
</SecondNode>
<SecondNode>
<FirstNodeKey>154></FirstNodeKey>
</SecondNode>
</DataSet>
I want to produce the following xml with XSLT:
<DataSet>
<FirstNode>
<UniqueKey>111</UniqueKey>
<OtherKey>552</OtherKey>
</FirstNode>
<FirstNode>
<UniqueKey>123</UniqueKey>
<OtherKey>552</OtherKey>
</FirstNode>
<SecondNode>
<FirstNodeKey>111</FirstNodeKey>
</SecondNode>
<SecondNode>
<FirstNodeKey>123></FirstNodeKey>
</SecondNode>
</DataSet>
<DataSet>
<FirstNode>
<UniqueKey>154</UniqueKey>
<OtherKey>553</OtherKey>
</FirstNode>
<SecondNode>
<FirstNodeKey>154></FirstNodeKey>
</SecondNode>
</DataSet>
Basically I want to group the FirstNodes by the OtherKey first, and then group by the UniqueKey and FirstNodeKey. Then each should be enclosed in <DataSet></DataSet>
. Can I do this by using grouping?
Thanks in advance for your help!
回答1:
It seems you simply want to group the FirstNode
elements by the OtherKey
child and then reference any SecondNode
elements based on current-group()/UniqueKey
:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output method="xml" indent="yes"/>
<xsl:key name="second" match="SecondNode" use="FirstNodeKey"/>
<xsl:template match="DataSet">
<xsl:variable name="ds" select="."/>
<xsl:for-each-group select="FirstNode" group-by="OtherKey">
<xsl:copy select="$ds">
<xsl:copy-of select="current-group(), key('second', current-group()/UniqueKey, .)"/>
</xsl:copy>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
That is XSLT 3 working with Saxon 9.8 (example at https://xsltfiddle.liberty-development.net/3NzcBtw) or Altova 2018, for XSLT 2 you could spell out the
<xsl:copy select="$ds">
<xsl:copy-of select="current-group(), key('second', current-group()/UniqueKey, .)"/>
</xsl:copy>
as
<DataSet>
<xsl:copy-of select="current-group(), key('second', current-group()/UniqueKey, $ds)"/>
</DataSet>
and of course if there are other nodes to process replace the xsl:mode
declaration with the identity template.
来源:https://stackoverflow.com/questions/52121756/xslt-do-a-group-by-twice-first-within-the-same-tag-and-then-by-2-different-ta