通过在 XSLT 中硬编码节点值对节点进行分组
Grouping Nodes by hardcoding node values in XSLT
<root>
<Entry>
<ID>1</ID>
<Details>
<Code>A1</Code>
<Value>1000</Value>
</Details>
</Entry>
<Entry>
<ID>2</ID>
<Details>
<Code>A2</Code>
<Value>2000</Value>
</Details>
</Entry>
<Entry>
<ID>3</ID>
<Details>
<Code>B1</Code>
<Value>3000</Value>
</Details>
</Entry>
<Entry>
<ID>4</ID>
<Details>
<Code>B2</Code>
<Value>4000</Value>
</Details>
</Entry>
</root>
我有这个输入 XML,我希望通过 XSLT 对其进行分组,其中分组通过 硬编码节点值 进行。让我详细解释一下:
需要根据节点 <Code>
中出现的代码参数进行分组,如下所示:
- 代码 'A1' 和 'A2' 需要组合在一起
- 代码 'B1' 和 'B2' 需要组合在一起
我最终总结了来自这些组中 <Value>
个节点的值。所以输出如下:
<Output>
<Code-group> A </Code-group>
<Sum> 3000 </Sum>
<Code-group> B </Code-group>
<Sum> 7000 </Sum>
</Output>
对于此要求,需要对分组值进行硬编码(将 A1、A2 分组为 A,将 B1、B2 分组为 B)。我使用 'hardcoded' 这个词是因为代码 (A1、A2、B1、B2) 可以按任何顺序出现,所以我想对值进行硬编码以查找分组而不是查找节点索引。
我查看了 for-each-group 方法以及 Muenchian Grouping 方法,但无法实现上述组映射。任何帮助表示赞赏!
提前致谢
编辑:映射 A1,A2 --> A & B1,B2 --> B 是一个通用示例,实际节点值与此完全不同,因此子字符串解决方案不起作用。这就是为什么我专注于硬编码来实现该映射。
如果您可以选择使用 for-each-group,我肯定会在 Muenchian 分组上使用它...
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<Output>
<xsl:for-each-group select="Entry" group-by="substring(Details/Code,1,1)">
<Code-group>
<xsl:value-of select="current-grouping-key()"/>
</Code-group>
<Sum>
<xsl:value-of select="sum(current-group()/Details/Value)"/>
</Sum>
</xsl:for-each-group>
</Output>
</xsl:template>
</xsl:stylesheet>
Fiddle: http://xsltfiddle.liberty-development.net/jxNakzX
如果您真的想对“A”-> A1、A2 和“B”-> B1、B2 映射进行硬编码,您可以使用 xsl:key 而不是分组...
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="A" match="Entry[Details/Code=('A1','A2')]" use="'A'"/>
<xsl:key name="B" match="Entry[Details/Code=('B1','B2')]" use="'B'"/>
<xsl:template match="/*">
<xsl:variable name="ctx" select="."/>
<Output>
<xsl:for-each select="('A','B')">
<xsl:variable name="key" select="."/>
<Code-group>
<xsl:value-of select="$key"/>
</Code-group>
<Sum>
<xsl:value-of select="sum($ctx/key($key,$key)/Details/Value)"/>
</Sum>
</xsl:for-each>
</Output>
</xsl:template>
</xsl:stylesheet>
硬编码要求很难理解。也许你想做这样的事情:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="entry" match="Entry" use="Details/Code"/>
<xsl:template match="/root">
<Output>
<Code-group> A </Code-group>
<Sum>
<xsl:value-of select="sum(key('entry', ('A1', 'A2'))/Details/Value)" />
</Sum>
<Code-group> B </Code-group>
<Sum>
<xsl:value-of select="sum(key('entry', ('B1', 'B2'))/Details/Value)" />
</Sum>
</Output>
</xsl:template>
</xsl:stylesheet>
<root>
<Entry>
<ID>1</ID>
<Details>
<Code>A1</Code>
<Value>1000</Value>
</Details>
</Entry>
<Entry>
<ID>2</ID>
<Details>
<Code>A2</Code>
<Value>2000</Value>
</Details>
</Entry>
<Entry>
<ID>3</ID>
<Details>
<Code>B1</Code>
<Value>3000</Value>
</Details>
</Entry>
<Entry>
<ID>4</ID>
<Details>
<Code>B2</Code>
<Value>4000</Value>
</Details>
</Entry>
</root>
我有这个输入 XML,我希望通过 XSLT 对其进行分组,其中分组通过 硬编码节点值 进行。让我详细解释一下:
需要根据节点 <Code>
中出现的代码参数进行分组,如下所示:
- 代码 'A1' 和 'A2' 需要组合在一起
- 代码 'B1' 和 'B2' 需要组合在一起
我最终总结了来自这些组中 <Value>
个节点的值。所以输出如下:
<Output>
<Code-group> A </Code-group>
<Sum> 3000 </Sum>
<Code-group> B </Code-group>
<Sum> 7000 </Sum>
</Output>
对于此要求,需要对分组值进行硬编码(将 A1、A2 分组为 A,将 B1、B2 分组为 B)。我使用 'hardcoded' 这个词是因为代码 (A1、A2、B1、B2) 可以按任何顺序出现,所以我想对值进行硬编码以查找分组而不是查找节点索引。
我查看了 for-each-group 方法以及 Muenchian Grouping 方法,但无法实现上述组映射。任何帮助表示赞赏!
提前致谢
编辑:映射 A1,A2 --> A & B1,B2 --> B 是一个通用示例,实际节点值与此完全不同,因此子字符串解决方案不起作用。这就是为什么我专注于硬编码来实现该映射。
如果您可以选择使用 for-each-group,我肯定会在 Muenchian 分组上使用它...
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<Output>
<xsl:for-each-group select="Entry" group-by="substring(Details/Code,1,1)">
<Code-group>
<xsl:value-of select="current-grouping-key()"/>
</Code-group>
<Sum>
<xsl:value-of select="sum(current-group()/Details/Value)"/>
</Sum>
</xsl:for-each-group>
</Output>
</xsl:template>
</xsl:stylesheet>
Fiddle: http://xsltfiddle.liberty-development.net/jxNakzX
如果您真的想对“A”-> A1、A2 和“B”-> B1、B2 映射进行硬编码,您可以使用 xsl:key 而不是分组...
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="A" match="Entry[Details/Code=('A1','A2')]" use="'A'"/>
<xsl:key name="B" match="Entry[Details/Code=('B1','B2')]" use="'B'"/>
<xsl:template match="/*">
<xsl:variable name="ctx" select="."/>
<Output>
<xsl:for-each select="('A','B')">
<xsl:variable name="key" select="."/>
<Code-group>
<xsl:value-of select="$key"/>
</Code-group>
<Sum>
<xsl:value-of select="sum($ctx/key($key,$key)/Details/Value)"/>
</Sum>
</xsl:for-each>
</Output>
</xsl:template>
</xsl:stylesheet>
硬编码要求很难理解。也许你想做这样的事情:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="entry" match="Entry" use="Details/Code"/>
<xsl:template match="/root">
<Output>
<Code-group> A </Code-group>
<Sum>
<xsl:value-of select="sum(key('entry', ('A1', 'A2'))/Details/Value)" />
</Sum>
<Code-group> B </Code-group>
<Sum>
<xsl:value-of select="sum(key('entry', ('B1', 'B2'))/Details/Value)" />
</Sum>
</Output>
</xsl:template>
</xsl:stylesheet>