在 XSLT 中分组数据后计算行数 [英] Count the lines after grouping data in XSLT

查看:29
本文介绍了在 XSLT 中分组数据后计算行数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在数据分组后获取输出中的行数.
XML 输入文件如下所示:

I need to get the number of rows in the output after the data have been grouped.
XML input file looks like this:

<?xml version='1.0' encoding='UTF-8'?>
<root>
      <entry>
             <ID>T-1149</ID>
             <Item_ID>FM1</Item_ID>
             <Item_Amount>
                        <Amount>20.00</Amount>
             </Item_Amount>
      </entry>
      <entry>
             <ID>T-1149</ID>
             <Item_ID>FM1</Item_ID>
             <Item_Amount>
                         <Amount>10.00</Amount>
             </Item_Amount>
      </entry>
      <entry>
             <ID>T-1142</ID>
             <Item_ID>FM1</Item_ID>
             <Item_Amount>
                          <Amount>10.00</Amount>
             </Item_Amount>
      </entry>
      <entry>
             <ID>T-1142</ID>
             <Item_ID>FM2</Item_ID>
             <Item_Amount>
                         <Amount>-50.00</Amount>
             </Item_Amount>
      </entry>
</root> 

固定宽度的输出将如下所示:

The output which is a fixed width will look like this:

Header1
T-1149                        FM1                      30.00
T-1142                        FM1                      10.00
T-1142                        FM2                     -50.00
TRAILER 5 15

预告片中的数字 5 是包括标题和预告片在内的行数.

The number 5 in the trailer is the count of lines including header and trailer.

我有这个代码,但这会计算 XML 文件中的所有条目:

I have this code but this counts all the entries in the XML file:

<xsl:variable name="count_invoice_line"
    select="count(root/entry)"/>

<xsl:variable name="header_line">
    <xsl:value-of select="1"/>
</xsl:variable>

<xsl:variable name="trailer_line">
    <xsl:value-of select="1"/>
</xsl:variable> 

<xsl:variable name="RightPadding"
    select="'                                                                                                                                                                                                                                                                                                                                                                                                                
 '"/>

<xsl:variable name="LeftPadding"
    select="'                                                                                         
'"/>
<xsl:function name="mf:PadLeft">
    <xsl:param name="string"/>
    <xsl:param name="length"/>
    <xsl:variable name="leftPad">
        <xsl:value-of
            select="substring($LeftPadding, 1, $length - string-length(string($string)))"/>
    </xsl:variable>
    <xsl:sequence select="concat($leftPad, $string)"/>
</xsl:function>

<xsl:function name="mf:PadRight">
    <xsl:param name="string"/>
    <xsl:param name="length"/>
    <xsl:sequence select="substring(concat($string, $RightPadding), 1, $length)"/>
</xsl:function>

<xsl:template match="/">

   <xsl:apply-templates/>
  <xsl:sequence
    select="accumulator-after('remainder-sum')"/>
    <Control_Header_Record>
        <RowIdentifier>
            <xsl:value-of select="mf:PadRight('HEADER', 6)"/>
        </RowIdentifier>          
    </Control_Header_Record>
    <Detail>
        <xsl:for-each-group select="root/entry"
            group-by="concat(ID, ' ', Item_ID)">
              <ID><xsl:value-of select="mf:PadRight(ID, 30)"/></ID>
              <Item_ID><xsl:value-of select="mf:PadRight(Item_ID, 3)"/>
                <xsl:value-of select="mf:PadLeft(Amount, 27)"/>
            </Row_Indentifier>

    </Detail>
    <Trailer_Record>
        <xsl:variable name="total_feed_line">
            <xsl:value-of select="$count_invoice_line + $header_line + $trailer_line"/>
        </xsl:variable>          
        <RowIdentifier><xsl:value-of select="mf:PadRight('TRAILER',8)"/></RowIdentifier>
        <Total_Feed_Line><xsl:value-of select="mf:PadRight($total_feed_line,2)"/></Total_Feed_Line>
        <Hash_Total_Value><xsl:value-of select="mf:PadRight($remainder-sum,15)"/></Hash_Total_Value>
    </Trailer_Record>
</xsl:template>

这段代码的输出是

Header1
T-1149                        FM1                      30.00
T-1142                        FM1                      10.00
T-1142                        FM2                     -50.00
TRAILER 6 15

由于输入文件中的 T-1149 有两个条目,它被计为 2,这就是为什么它得到 6.我只是需要输出中的总行数.我尝试将分组结果放在一个变量中并调用该变量进行计数:

Since the T-1149 from the input file has two entries, it is counted as 2 thats why it's getting 6. I just the need total number of lines in the output. I tried putting the grouping result in a variable and call the variable for the count:

<Detail>
<xsl:variable="row">
        <xsl:for-each-group select="root/entry"
            group-by="concat(ID, ' ', Item_ID)">
              <ID><xsl:value-of select="mf:PadRight(ID, 30)"/></ID>
              <Item_ID><xsl:value-of select="mf:PadRight(Item_ID, 3)"/>
                <xsl:value-of select="mf:PadLeft(Amount, 27)"/>
            </Row_Indentifier>
     </xsl:variable>
    </Detail>


  <xsl:value-of select="count($rows)"/>

但我收到编译错误,说没有以下同级指令的变量(行)无效,然后变量 $rows 尚未声明.我正在使用氧气来测试这一点,但不确定在 XSLT2.0 中是否比 3.0 更简单.但我需要把它和我的其他代码放在一起 合并行数和哈希值 - 在 XSLT 中获取余数 这是一个关于获取哈希总值的问题

but I'm getting complilation error saying a variable (rows) with no following sibling instructions has no effect and then variable $rows has not been declared. I'm using oxygen to test this and not sure if it is simpler to be done in XSLT2.0 than 3.0. but I need to get this along with my other code here Count of consolidated lines and Hash value - getting the remainder in XSLT which is an issue about getting the hash total value

谢谢.

推荐答案

你得到第一个错误,因为带有 xsl:variable 的变量声明是在 Details 内部完成的文字结果元素,但您尝试使用该变量不是该变量声明的同级,即也在 Details 元素内部,但在它之外.

You get the first error because the variable declaration with xsl:variable is done inside of the Details literal result element but your attempt to use the variable is not a sibling of that variable declaration, i.e. also inside of the Details element, but outside of it.

所以这是您可以进行的必要且简单的修复.

So that is a necessary and easy fix you can make.

除此之外,您的代码不清楚(有一个杂散的</Row_Indentifier>),如果您的目标是对条目 元素然后我希望 xsl:for-each-group 中的一些内容为每个组创建组"包装元素或通过累积合并属于一个组的条目"元素金额或其他数据.

Other than that your code is not clear (there is a stray </Row_Indentifier>), nor is your wanted result, if your aim is to group the entry elements then I would expect some content inside of the xsl:for-each-group to either create "group" wrapper element for each group or to merge the "entry" elements belonging to a group by accumulating amout or other data.

因此,您需要详细说明变量内容所需的结果结构、要计数的元素或项目、要查找的计数结果.

So you will need to elaborate on which result structure you want for the variable content, which elements or items you want to count, which result you are looking for for the count.

举个例子,代码

<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:template match="root">
      <xsl:variable name="grouped-entries" as="element(entry)*">
          <xsl:for-each-group select="entry" composite="yes" group-by="ID, Item_ID">
              <xsl:copy>
                  <xsl:apply-templates/>
              </xsl:copy>
          </xsl:for-each-group>
      </xsl:variable>
      <xsl:sequence select="count($grouped-entries), $grouped-entries"/>
  </xsl:template>

  <xsl:template match="Item_Amount/Amount">
      <xsl:copy>
          <xsl:value-of select="sum(current-group()/Item_Amount/Amount)"/>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

将相同 IDItem_IDentry 元素组合成一个,其中 Amount 为所有元素求和组中的条目,因此对于您的示例,您在变量中有 3 条目元素,并且您有您似乎想要输出的总和(https://xsltfiddle.liberty-development.net/pPJ9hE9)

groups the entry elements of the same ID and Item_ID into one where the Amount is summed for all entries in the group, so for your example you then have 3 entry elements in the variable and you have the sums you seem to want to output (https://xsltfiddle.liberty-development.net/pPJ9hE9)

将分组结果转换为另一种格式是一个不同的步骤,但一旦您了解了分组结果的类型和结构,并清楚了解如何创建所需的格式,就应该很容易了.

Transforming that grouping result into another format is a different step but should rather easy once you have understood the type and structure of the grouping result and have a clear understanding on how to create the format you need.

这篇关于在 XSLT 中分组数据后计算行数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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