XSLT - XML ​​- Для каждой группы с xsl: выбрать - PullRequest
0 голосов
/ 25 июня 2018

У меня есть следующий XML-файл:

<report>
    <page name="Simple MasterPage">
        <table id="__bookmark_1">
            <table-band band-type="BAND_HEADER">
                <row>
                    <cell>
                        <label>OPTYPE</label>
                    </cell>
                    <cell>
                        <label>REPORTNUM</label>
                    </cell>
                    <cell>
                        <label>REPORTNAME</label>
                    </cell>
                    <cell>
                        <label>CREATIONDATE</label>
                    </cell>
                    <cell>
                        <label>PERSONNAME</label>
                    </cell>
                    <cell>
                        <label>PERSONID</label>
                    </cell>
                    <cell>
                        <label>NUMELEM</label>
                    </cell>
                    <cell>
                        <label>COUNTRY</label>
                    </cell>
                    <cell>
                        <label>NATIONALITY</label>
                    </cell>
                    <cell>
                        <label>IDTYPE</label>
                    </cell>
                    <cell>
                        <label>STREET</label>
                    </cell>
                    <cell>
                        <label>CITY</label>
                    </cell>
                    <cell>
                        <label>POSTCODE</label>
                    </cell>
                    <cell>
                        <label>BIRTHDATE</label>
                    </cell>
                     <cell>
                        <label>GENDER</label>
                    </cell>
                    <cell>
                        <label>ALTPERSONID</label>
                    </cell>
                </row>
            </table-band>
            <table-band band-type="BAND_DETAIL">
                <row>
                    <cell>
                        <data>A</data>
                    </cell>
                    <cell>
                        <data>1</data>
                    </cell>
                    <cell>
                        <data>firstReport</data>
                    </cell>
                    <cell>
                        <data>2017-01-31</data>
                    </cell>
                    <cell>
                        <data>Alex Jones</data>
                    </cell>
                    <cell>
                        <data>100001</data>
                    </cell>
                    <cell>
                        <data>1</data>
                    </cell>
                    <cell>
                        <data>Portugal</data>
                    </cell>
                     <cell>
                        <data>Portuguese</data>
                    </cell>
                    <cell>
                        <data>i1</data>
                    </cell>
                    <cell>
                        <data>Jones Street</data>
                    </cell>
                    <cell>
                        <data>Lisbon</data>
                    </cell>
                    <cell>
                        <data>2600</data>
                    </cell>
                    <cell>
                        <data>1997-02-04</data>
                    </cell>
                    <cell>
                        <data>M</data>
                    </cell>
                    <cell>
                        <data></data>
                    </cell>
                </row>
            </table-band>
             <table-band band-type="BAND_DETAIL">
                <row>
                    <cell>
                        <data>B</data>
                    </cell>
                    <cell>
                        <data>1</data>
                    </cell>
                    <cell>
                        <data>firstReport</data>
                    </cell>
                    <cell>
                        <data>2017-01-31</data>
                    </cell>
                    <cell>
                        <data>Ana Maria</data>
                    </cell>
                    <cell>
                        <data>100002</data>
                    </cell>
                    <cell>
                        <data>2</data>
                    </cell>
                    <cell>
                        <data>Portugal</data>
                    </cell>
                     <cell>
                        <data>Portuguese</data>
                    </cell>
                    <cell>
                        <data>i2</data>
                    </cell>
                    <cell>
                        <data>Maria Street</data>
                    </cell>
                    <cell>
                        <data>Lisbon</data>
                    </cell>
                    <cell>
                        <data>2600</data>
                    </cell>
                    <cell>
                        <data>1997-02-06</data>
                    </cell>
                    <cell>
                        <data>F</data>
                    </cell>
                    <cell>
                        <data>alt1</data>
                    </cell>
                </row>
            </table-band>
            <table-band band-type="BAND_DETAIL">
                <row>
                    <cell>
                        <data>B</data>
                    </cell>
                    <cell>
                        <data>1</data>
                    </cell>
                    <cell>
                        <data>firstReport</data>
                    </cell>
                    <cell>
                        <data>2017-01-31</data>
                    </cell>
                    <cell>
                        <data>Ana Maria</data>
                    </cell>
                    <cell>
                        <data>100002</data>
                    </cell>
                    <cell>
                        <data>3</data>
                    </cell>
                    <cell>
                        <data>Portugal</data>
                    </cell>
                     <cell>
                        <data>Portuguese</data>
                    </cell>
                    <cell>
                        <data>i2</data>
                    </cell>
                    <cell>
                        <data>Maria Street</data>
                    </cell>
                    <cell>
                        <data>Lisbon</data>
                    </cell>
                    <cell>
                        <data>2600</data>
                    </cell>
                    <cell>
                        <data>1997-02-06</data>
                    </cell>
                    <cell>
                        <data>F</data>
                    </cell>
                    <cell>
                        <data>alt1</data>
                    </cell>
                </row>
            </table-band>
            <table-band band-type="BAND_DETAIL">
                <row>
                    <cell>
                        <data>B</data>
                    </cell>
                    <cell>
                        <data>1</data>
                    </cell>
                    <cell>
                        <data>firstReport</data>
                    </cell>
                    <cell>
                        <data>2017-01-31</data>
                    </cell>
                    <cell>
                        <data>Ana Maria</data>
                    </cell>
                    <cell>
                        <data>100002</data>
                    </cell>
                    <cell>
                        <data>4</data>
                    </cell>
                    <cell>
                        <data>Portugal</data>
                    </cell>
                     <cell>
                        <data>Portuguese</data>
                    </cell>
                    <cell>
                        <data>i2</data>
                    </cell>
                    <cell>
                        <data>Maria Street</data>
                    </cell>
                    <cell>
                        <data>Lisbon</data>
                    </cell>
                    <cell>
                        <data>2600</data>
                    </cell>
                    <cell>
                        <data>1997-02-06</data>
                    </cell>
                    <cell>
                        <data>F</data>
                    </cell>
                    <cell>
                        <data>alt1</data>
                    </cell>
                </row>
            </table-band>
            <table-band band-type="BAND_DETAIL">
                <row>
                    <cell>
                        <data>A</data>
                    </cell>
                    <cell>
                        <data>1</data>
                    </cell>
                    <cell>
                        <data>firstReport</data>
                    </cell>
                    <cell>
                        <data>2017-01-31</data>
                    </cell>
                    <cell>
                        <data>Alex Jones</data>
                    </cell>
                    <cell>
                        <data>100002</data>
                    </cell>
                    <cell>
                        <data>5</data>
                    </cell>
                    <cell>
                        <data>Portugal</data>
                    </cell>
                     <cell>
                        <data>Portuguese</data>
                    </cell>
                    <cell>
                        <data>i1</data>
                    </cell>
                    <cell>
                        <data>Jones Street</data>
                    </cell>
                    <cell>
                        <data>Lisbon</data>
                    </cell>
                    <cell>
                        <data>2600</data>
                    </cell>
                    <cell>
                        <data>1997-02-04</data>
                    </cell>
                    <cell>
                        <data>M</data>
                    </cell>
                    <cell>
                        <data></data>
                    </cell>
                </row>
            </table-band>
        </table>
    </page>
</report>

Это часть XSLT, которую я использую для его преобразования, и пользователь @Parfait научил меня, как строить на очень похожем посте. Если OPTYPE - B, то у вывода будет другой выходной элемент с именем altPersonID; Затем idType установит атрибуты personInfo.

    <xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output method="xml" omit-xml-declaration="no" indent="yes" encoding="utf-8"/>
<xsl:strip-space elements="*"/>


....

    <xsl:for-each-group select="table-band" group-by="row/cell[position()=
                      count(ancestor::table/table-band[1]/row/cell[label='PERSONNAME']/preceding-sibling::*)+1]/data">

    <xsl:choose>
    <xsl:when test="$op_type = 'A'">

        <xsl:choose>
        <xsl:when test="$id_type = 'i1'"> 

        ....

        <!--HERE IM USING FOR EACH GROUP-->

            <listOfElements>
                <xsl:for-each-group select="current-group()" group-by="row/cell[position()=
                      count(ancestor::table/table-band[1]/row/cell[label='NUMELEM']/preceding-sibling::*)+1]">
                    <element>
                        <xsl:call-template name="build-attrib">
                            <xsl:with-param name="label_val">CREATIONDATE</xsl:with-param>
                            <xsl:with-param name="attrib_nm">creationDate</xsl:with-param>
                        </xsl:call-template>
                        <xsl:call-template name="build-attrib">
                            <xsl:with-param name="label_val">NUMELEM</xsl:with-param>
                            <xsl:with-param name="attrib_nm">numElem</xsl:with-param>
                        </xsl:call-template>
                   </element>
                </xsl:for-each-group>
            </listOfElements>
        ....

      </xsl:for-each-group>
</xsl:template>

</xsl:stylesheet>

в основном он выводится всегда одинаково, независимо от того, является ли OPTYPE B или A и IDTYPE i1 или i2

Ответы [ 2 ]

0 голосов
/ 25 июня 2018

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

<reports>
 <report>
  <OPTYPE>EI</OPTYPE>
  <REPORT_NUM>1</REPORT_NUM>
  <REPORT_NAME>...</REPORT_NAME> 
  <CREATION_DATE>2017-01-31</CREATION_DATE>
  ...
 </report>
 <report>
  ...
 </report>
</reports>

, а затем выполнить конкретное преобразование, включающее группировку и т. Д.

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

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

Существует множество способов организации конвейера преобразований в XSLT. Вы можете сделать это в одной таблице стилей, записав результат первой фазы в переменную, а затем используя эту переменную в качестве входных данных для второй фазы; или вы можете использовать несколько таблиц стилей, соединенных вместе, используя различные технологии, включая XProc, Java-программы, Ant-сценарии, сценарии оболочки или любое количество основанных на XSLT каркасов приложений.

0 голосов
/ 25 июня 2018

Трудно дать точный ответ, потому что вы не показали ожидаемый результат, но похоже, что проблема в том, что вы объявили переменные op_type и id_type перед xsl:for-each-group

<xsl:template match="table">
  <xsl:variable name="op_type">
    <xsl:value-of select="table-band/row/cell[position()=1]/data"/>
  </xsl:variable>
  <xsl:variable name="id_type">
    <xsl:value-of select="table-band/row/cell[position()=10]/data"/>
  </xsl:variable>
  <xsl:for-each-group select="table-band" group-by="row/cell[position()=
                  count(ancestor::table/table-band[1]/row/cell[label='PERSONNAME']/preceding-sibling::*)+1]/data">
    <xsl:choose>
       ....

Это означает, что (так как вы используете XSLT 3.0), эта переменная op_type будет содержать значение всех ячеек "optype", объединенных в одну строку.Вы могли бы увидеть это, если бы вы сделали xsl:value-of после вашего объявления

<xsl:value-of select="$op_type" />

Это возвращает следующее

EI EU EU EU EI

Что вам нужно сделать, переместите объявление в xsl:for-each-group, такчто он выбирает значение для первой строки в группе.

<xsl:template match="table">
  <xsl:for-each-group select="table-band" group-by="row/cell[position()=
                      count(ancestor::table/table-band[1]/row/cell[label='PERSONNAME']/preceding-sibling::*)+1]/data">
    <xsl:variable name="op_type" select="row/cell[position()=1]/data"/>
    <xsl:variable name="id_type" select="row/cell[position()=10]/data" />
    <xsl:choose>
       ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...