Подсчитать количество строк после группировки данных в XSLT - PullRequest
0 голосов
/ 27 января 2020

Мне нужно получить количество строк в выходных данных после группировки данных.
XML входной файл выглядит следующим образом:

<?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> 

Выход с фиксированной шириной будет выглядеть так:

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

Число 5 в трейлере - это количество строк, включая заголовок и трейлер.

У меня есть этот код, но он подсчитывает все записи в файле XML:

<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. Мне просто нужно общее количество строк в выводе. Я попытался поместить результат группировки в переменную и вызвать переменную для счетчика:

<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)"/>

, но я получаю ошибку компиляции, говорящую, что переменная (строки) без следующих инструкций родного брата не имеет никакого эффекта, а затем переменная $ строк не было объявлено. Я использую кислород, чтобы проверить это, и не уверен, проще ли это сделать в XSLT2.0, чем в 3.0. но мне нужно получить это вместе с другим моим кодом здесь Количество консолидированных строк и значение Ha sh - получение остатка в XSLT , что является проблемой получения общего значения ha sh

Спасибо.

1 Ответ

0 голосов
/ 27 января 2020

Вы получаете первую ошибку, потому что объявление переменной с xsl:variable выполняется внутри буквального элемента результата Details, но ваша попытка использовать переменную не является родственником этого объявления переменной, т. Е. Также внутри Details элемент, но за его пределами.

Так что это необходимое и простое исправление, которое вы можете сделать.

Кроме того, что ваш код неясен (есть отклонение </Row_Indentifier>), и не является желаемым результатом, если ваша цель - сгруппировать элементы entry, тогда я ожидал бы, что некоторый контент внутри xsl:for-each-group либо создаст элемент-обертку «group» для каждой группы, либо объединит элементы «entry», принадлежащие группа, накапливая данные или другие данные.

Таким образом, вам нужно будет уточнить, какую структуру результатов вы хотите для переменного содержимого, какие элементы или элементы вы хотите подсчитать, какой результат вы ищете для подсчета .

Для примера, код

<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>

группирует элементы entry одинаковых ID и Item_ID в тот, где Amount суммируется для всех записей в группе, так что для вашего примера у вас есть 3 элементы записи в переменной, и у вас есть суммы, которые вы хотите вывести (https://xsltfiddle.liberty-development.net/pPJ9hE9)

Преобразование этого результата группировки в другой формат - это другой шаг, но он должен быть довольно простым, если вы понимаете тип и структуру результата группировки и четко понимаете, как создать нужный вам формат.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...