XSLT转换中基于条件的分组并将其放在一行中 [英] Grouping based on conditions and putting them into a single row in XSLT Transformation

查看:19
本文介绍了XSLT转换中基于条件的分组并将其放在一行中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我面临着一个XML转换的问题。我需要转换CSV文件中的输出,用‘,’分隔。

XML:

<Root>
<Employees>
<Employee>
<Co_Code>DEEP1</Co_Code>
<ID>12345</ID>
</Employee>
<Type Descriptor="Phone"></Type>
<amount1>8</amount1>
</Employees>
<Employees>
<Employee>
<Co_Code>DEEP1</Co_Code>
<ID>12345</ID>
</Employee>
<Type Descriptor="Phone"></Type>
<amount>6</amount>
</Employees>
<Employees>
<Employee>
<Co_Code>DEEP1</Co_Code>
<ID>12345</ID>
</Employee>
<Type Descriptor="Food"></Type>
<amount>8</amount>
</Employees>
<Employees>
<Employee>
<Co_Code>DEEP1</Co_Code>
<ID>12345</ID>
</Employee>
<Type Descriptor="Travel"></Type>
<amount>8</amount>
</Employees>
<Employees>
<Employee>
<Co_Code>DEEP1</Co_Code>
<ID>12345</ID>
</Employee>
<Type Descriptor="Other"></Type>
<amount>800</amount>
</Employees>
<Employees>
<Employee>
<Co_Code>DEEP1</Co_Code>
<ID>12346</ID>
</Employee>
<Type Descriptor="Phone"></Type>
<amount>8</amount>
</Employees>
<Employees>
<Employee>
<Co_Code>DEEP1</Co_Code>
<ID>12346</ID>
</Employee>
<Type Descriptor="Phone"></Type>
<amount>8</amount>
</Employees>
<Employees>
<Employee>
<Co_Code>DEEP1</Co_Code>
<ID>12346</ID>
</Employee>
<Type Descriptor="Other"></Type>
<amount>8</amount>
</Employees>
<Employees>
<Employee>
<Co_Code>DEEP1</Co_Code>
<ID>12346</ID>
</Employee>
<Type Descriptor="Food"></Type>
<amount>8</amount>
</Employees>
</Root>

当前正在使用XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

<xsl:param name="sep" select="', '"/>

<xsl:output method="text"/>

<xsl:template match="Root">
  <xsl:value-of select="'Co Code', 'ID', 'type', 'amount'" separator="{$sep}"/>
  <xsl:text>&#10;</xsl:text>
  <xsl:for-each-group select="Employees" group-adjacent="Type/@Descriptor">
    <xsl:if test="position() gt 1"><xsl:text>&#10;</xsl:text></xsl:if>
    <xsl:value-of select="Employee/Co_Code, Employee/ID, current-grouping-key(), sum(current-group()/amount)"
      separator="{$sep}"/>
  </xsl:for-each-group>
</xsl:template>

</xsl:stylesheet>

当前正在生成以下格式的输出:

Co Code, ID, type, amount
DEEP1, 12345, Phone, 6
DEEP1, 12345, Food, 8
DEEP1, 12345, Travel, 8
DEEP1, 12345, Other, 800
DEEP1, 12346, Phone, 16
DEEP1, 12346, Other, 8
DEEP1, 12346, Food, 8

但我需要将这几行排列成列。 我正在尝试获得以下格式的输出。 电话和食物的员工合计应写在一个单独的列中,对于其他类型,应创建一个单独的行,电话和食物列为空。

Co Code, ID,  Phone , Food, type,  amount
DEEP1, 12345,   6   ,  8  ,       ,
DEEP1, 12345,       ,     , Travel, 8
DEEP1, 12345,               Other, 800
DEEP1, 12346,  16   ,  8  ,       ,
DEEP1, 12346,       ,     , Other, 8

请给我一些实现这一点的想法。

感谢Martin Honnen帮助我。

推荐答案

您可能希望首先按员工ID分组

<xsl:for-each-group select="Employees"  
                    group-by="Employee/ID">

然后有一个用于输出"Food"和"phone"值的特定行

<xsl:value-of select="Employee/Co_Code, 
                      current-grouping-key(), 
                      sum(current-group()[Type/@Descriptor = 'Phone']/amount), 
                      sum(current-group()[Type/@Descriptor = 'Food']/amount), 
                      '', 
                      ''"  separator="{$sep}"/>

在当前组中,您可以按描述符对非"Food"和"phone"条目进行分组(只有在描述符可以重复的情况下才需要这样做)

 <xsl:for-each-group select="current-group()[not(Type/@Descriptor = ('Phone', 'Food'))]" 
                     group-by="Type/@Descriptor">

那么它也是为此输出一行的简单情况。

尝试此XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

<xsl:param name="sep" select="', '"/>

<xsl:output method="text"/>

<xsl:template match="Root">
    <xsl:value-of select="'Co Code', 'ID', 'type', 'amount'" separator="{$sep}"/>
    <xsl:text>&#10;</xsl:text>
    <xsl:for-each-group select="Employees" group-by="Employee/ID">
        <xsl:value-of select="Employee/Co_Code, current-grouping-key(), sum(current-group()[Type/@Descriptor = 'Phone']/amount), sum(current-group()[Type/@Descriptor = 'Food']/amount), '', ''"  separator="{$sep}"/>
        <xsl:text>&#10;</xsl:text>
        <xsl:for-each-group select="current-group()[not(Type/@Descriptor = ('Phone', 'Food'))]" group-by="Type/@Descriptor">
            <xsl:value-of select="Employee/Co_Code, '', '', sum(current-group()/amount), current-group()/Type/@Descriptor"  separator="{$sep}"/>
            <xsl:text>&#10;</xsl:text>
        </xsl:for-each-group>
    </xsl:for-each-group>
</xsl:template>

</xsl:stylesheet>

这篇关于XSLT转换中基于条件的分组并将其放在一行中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆