XSLT мюнхенская группировка по значению в дочернем узле

Я пытаюсь преобразовать sap iDoc в другой файл xml с картой BizTalk, написанной на xslt. Проблема в том, что мне нужно сгруппировать узлы на основе значения, которое мы можем найти в конкретном подузле.

Мюнхенская группировка (я использую XSLT 1.0) кажется решением, но я не могу понять, как заставить ее работать, поскольку мне нужно сгруппировать по значению подузла.

<Receive>
    <idocData>
        <E2EDL20003GRP>
            <E2EDL2003>
                <ParentValue>PV</ParentValue>
            </E2EDL2003>
            ...
            <E2EDL24007GRP>
                <E2EDL24007>
                    <ChildValue>CHV1</ChildValue>
                </E2EDL24007>
                <E2EDL43000>
                    <QUALF>C</QUALF>
                    <BELNR>0000045690</BELNR>
                </E2EDL43000>
                ...
            </E2EDL24007GRP>
            <E2EDL24007GRP>
                <E2EDL24007>
                    <ChildValue>CHV2</ChildValue>
                </E2EDL24007>
                <E2EDL43000>
                    <QUALF>C</QUALF>
                    <BELNR>0000045690</BELNR>
                </E2EDL43000>
                ...
            </E2EDL24007GRP>
            <E2EDL24007GRP>
                <E2EDL24007>
                    <ChildValue>CHV3</ChildValue>
                </E2EDL24007>
                <E2EDL43000>
                    <QUALF>C</QUALF>
                    <BELNR>0000045691</BELNR>
                </E2EDL43000>
                ...
            </E2EDL24007GRP>
        </E2EDL20003GRP>
    </idocData>
</Receive>

После применения преобразования XSLT я ищу:

<ns0:Root>
    <RecordA>
        <ID>PV</ID>
        <RecordB>
            <ID>0000045690</ID>
            <RecordC>
                <Value>CHV1</Value>
            </RecordC>
            <RecordC>
                <Value>CHV2</Value>
            </RecordC>
        </RecordB>
        <RecordB>
            <ID>0000045691</ID>
            <RecordC>
                <Value>CHV3</Value>
            </RecordC>
        </RecordB>
    </RecordA>
</ns0:Root>

Как видите, мне нужно сгруппировать E2EDL24007GRP по E2EDL43000[QUALF='C']/BELNR. Я попробовал следующую мюнхенскую группировку:

<xsl:key name="command" match="s0:E2EDL24007GRP" use="s0:E2EDL43000[s0:QUALF='C']/s0:BELNR" />

<xsl:template match="/">
    <xsl:apply-templates select="/s1:Receive" />
</xsl:template>

<xsl:template match="/s1:Receive/s1:idocData">
    <xsl:for-each select="s0:E2EDL20003GRP">
        <ns0:Root>
            <!-- Record A -->
            <RecordA>
                <ID>
                    <xsl:value-of select="s0:E2EDL2003/s0:ParentValue" />
                </ID>
                <xsl:apply-templates select="s0:E2EDL24007GRP[generate-id()=generate-id(key('command',s0:E2EDL43000[s0:QUALF='C']/s0:BELNR)[1])]"/>
            </RecordA>
        </ns0:Root>
    </xsl:for-each>
</xsl:template>

<xsl:template match="E2EDL24007GRP">
...
</xsl:template>

Но это вообще не сработало, есть идеи?


person Gosfly    schedule 08.10.2020    source источник
comment
Может ли быть более одного E2EDL20003GRP? Если да, могут ли два элемента E2EDL24007GRP иметь одинаковое значение BELNR, но принадлежать разным родителям E2EDL20003GRP?   -  person michael.hor257k    schedule 08.10.2020
comment
Нет, если имеется более одного E2EDL20003GRP (что будет крайне редко), значения BELNR будут другими. Они могут быть идентичными только в одном и том же E2EDL20003GR.   -  person Gosfly    schedule 08.10.2020


Ответы (1)


Следующая таблица стилей:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns0="http://example.com">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />

<xsl:key name="k" match="E2EDL24007GRP" use="E2EDL43000/BELNR" />

<xsl:template match="/Receive">
    <ns0:Root>
        <xsl:for-each select="idocData/E2EDL20003GRP">
            <RecordA>
                <ID>
                    <xsl:value-of select="E2EDL2003/ParentValue" />
                </ID>
                <xsl:for-each select="E2EDL24007GRP[generate-id()=generate-id(key('k', E2EDL43000/BELNR)[1])]">
                    <RecordB>
                        <ID>
                            <xsl:value-of select="E2EDL43000/BELNR" />
                        </ID>
                        <xsl:for-each select="key('k', E2EDL43000/BELNR)">
                            <RecordC>
                                <Value>
                                    <xsl:value-of select="E2EDL24007/ChildValue" />
                                </Value>
                            </RecordC>
                         </xsl:for-each>
                    </RecordB>
                </xsl:for-each>
            </RecordA>
        </xsl:for-each>
    </ns0:Root>
</xsl:template>

</xsl:stylesheet>

примененный к вашему примеру ввода, даст:

Результат

<?xml version="1.0" encoding="UTF-8"?>
<ns0:Root xmlns:ns0="http://example.com">
  <RecordA>
    <ID>PV</ID>
    <RecordB>
      <ID>0000045690</ID>
      <RecordC>
        <Value>CHV1</Value>
      </RecordC>
      <RecordC>
        <Value>CHV2</Value>
      </RecordC>
    </RecordB>
    <RecordB>
      <ID>0000045691</ID>
      <RecordC>
        <Value>CHV3</Value>
      </RecordC>
    </RecordB>
  </RecordA>
</ns0:Root>

Примечание.

  1. В вашем примере ввода нет пространств имен;
  2. Ваш вывод имеет префикс, не привязанный к пространству имен, что недопустимо; Я использовал поддельное пространство имен для создания правильно оформленного XML-документа.
person michael.hor257k    schedule 08.10.2020