Группировка xml записей с необходимыми дочерними элементами на основе одного элемента в xslt - PullRequest
0 голосов
/ 22 апреля 2020

Я пытаюсь сгруппировать XML записей, основываясь на условии, что одно поле имеет одинаковые данные в остальных записях. Мы получим данные A_ROW, которые содержат номер документа, и я сгруппировал записи B_ROW под A_ROW, который имеет тот же номер документа. Может кто-нибудь помочь, пожалуйста, чтобы прочитать и сгруппировать xml записей в xslt.

<recordSet>
<A_Row><company_code>1234</company_code>
        <document_num>5606</document_num>
        <document_type>CS</document_type>
        <doc_date>20190206</doc_date>
</A_Row>
<B_Row>
<document_num>5606</document_num>
        <pos>001</pos>
        <account>4564343</account>
        <account_type>ss</account_type>
</B_Row>
<B_Row>
<document_num>5606</document_num>
        <pos>001</pos>
        <account>4564344</account>
        <account_type>ss</account_type>
</B_Row>
<A_Row><company_code>1234</company_code>
        <document_num>5607</document_num>
        <document_type>CS</document_type>
        <doc_date>20190206</doc_date>
</A_Row>
<B_Row>
<document_num>5607</document_num>
        <pos>001</pos>
        <account>4564346</account>
        <account_type>ss</account_type>
</B_Row>
<B_Row>
<document_num>5607</document_num>
        <pos>001</pos>
        <account>4564342</account>
        <account_type>ss</account_type>
</B_Row>
<A_Row>
    <company_code>1234</company_code>
        <document_num>5608</document_num>
        <document_type>CS</document_type>
        <doc_date>20190206</doc_date>
</A_Row>
<B_Row>
<document_num>5608</document_num>
        <pos>001</pos>
        <account>4564349</account>
        <account_type>ss</account_type>
</B_Row>


</recordSet>

XSLT-код:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:ns="http://springer.com/xi/SAP/MEDIASUITE">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="Recordset">
        <xsl:for-each select="BT_ROW">
            <xsl:element name="BT_ROW">
                <xsl:apply-templates/>
                <xsl:variable name="document" select="/ns:MT_MEDIASUITE_ORDER_DATA/Recordset/BT_ROW/document_number"/>
                <xsl:for-each select="/ns:MT_MEDIASUITE_ORDER_DATA/Recordset/BS_ROW">
                    <xsl:if test="/ns:MT_MEDIASUITE_ORDER_DATA/Recordset/BS_ROW/document_number =$document">

                    <xsl:element name="BS_ROW">
                    <xsl:apply-templates/>
                    </xsl:element>

                    </xsl:if>
                </xsl:for-each>

            </xsl:element>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Ожидаемый результат:

<recordSet>
<A_Row><company_code>1234</company_code>
        <document_num>5606</document_num>
        <document_type>CS</document_type>
        <doc_date>20190206</doc_date>
    <B_Row>
        <document_num>5606</document_num>
            <pos>001</pos>
            <account>4564343</account>
            <account_type>ss</account_type>
    </B_Row>
    <B_Row>
        <document_num>5606</document_num>
            <pos>001</pos>
            <account>4564344</account>
            <account_type>ss</account_type>
    </B_Row>
</A_Row>

<A_Row>
<company_code>1234</company_code>
        <document_num>5607</document_num>
        <document_type>CS</document_type>
        <doc_date>20190206</doc_date>
    <B_Row>
        <document_num>5607</document_num>
            <pos>001</pos>
            <account>4564346</account>
            <account_type>ss</account_type>
    </B_Row>
    <B_Row>
        <document_num>5607</document_num>
            <pos>001</pos>
            <account>4564342</account>
            <account_type>ss</account_type>
    </B_Row>
</A_Row>

<A_Row>
    <company_code>1234</company_code>
        <document_num>5608</document_num>
        <document_type>CS</document_type>
        <doc_date>20190206</doc_date>
    <B_Row>
       <document_num>5608</document_num>
           <pos>001</pos>
           <account>4564349</account>
           <account_type>ss</account_type>
    </B_Row>

</A_Row>

</recordSet>

Ответы [ 2 ]

0 голосов
/ 26 апреля 2020

Я использовал приведенный ниже код, и он работал нормально

<xsl:element name="A_ROW">
				<xsl:apply-templates/>
				<xsl:variable name="doc_num" select="document_number"/>
				<xsl:variable name="pos1" select="fn:position()"/>
				<xsl:for-each select="//B_ROW">
					<xsl:variable name="pos" select="fn:position()"/>
					<xsl:if test="//B_ROW[$pos]/document_number=$doc_num">
						<xsl:element name="BS_ROW">
							<xsl:apply-templates/>
						</xsl:element>
					</xsl:if>
				</xsl:for-each>
	</xsl:element>
0 голосов
/ 22 апреля 2020

Для входной выборки, где каждая "группа", кажется, начинается с A_Row, достаточно использовать group-by и поверхностную копию первого элемента, чтобы затем заполнить его дочерними элементами и хвостом группы:

<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:strip-space elements="*"/>
  <xsl:output indent="yes"/>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="recordSet">
      <xsl:copy>
          <xsl:for-each-group select="*" group-by="document_num">
              <xsl:copy>
                  <xsl:apply-templates select="node(), tail(current-group())"/>
              </xsl:copy>
          </xsl:for-each-group>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/naZXVEZ

...