XSLT 1.0: преобразование IDOC в AdsML
Мне нужно преобразовать SAP IDOC xml в формат AdsML. Но абстрактный вопрос: как преобразовать xml1 в xml2?
xml1:
<E1BPBUSISM008_ITEM_OUT>
<ITEM_NUMBER>010</ITEM_NUMBER>
</E1BPBUSISM008_ITEM_OUT>
<E1BPBUSISM008_ITEM_OUT>
<ITEM_NUMBER>020</ITEM_NUMBER>
</E1BPBUSISM008_ITEM_OUT>
<E1BPBUSISM008_AD_SPEC_AD_OU>
<ITEM_NUMBER>010</ITEM_NUMBER>
<PLANNED_WIDTH>1.851</PLANNED_WIDTH>
<PLANNED_HEIGHT>0.000</PLANNED_HEIGHT>
</E1BPBUSISM008_AD_SPEC_AD_OU>
<E1BPBUSISM008_AD_SPEC_AD_OU>
<ITEM_NUMBER>020</ITEM_NUMBER>
<PLANNED_WIDTH>2.37</PLANNED_WIDTH>
<PLANNED_HEIGHT>0.000</PLANNED_HEIGHT>
</E1BPBUSISM008_AD_SPEC_AD_OU>
в xml2:
<Ad>
<ad-number>010<ad-number>
<width>1.851</width>
<height>0.000</height>
</Ad>
<Ad>
<ad-number>020<ad-number>
<width>2.37</width>
<height>0.000</height>
</Ad>
Здесь я попробовал метод Мюнхена, но даже если это правильное решение для этого случая, не уверен, как его завершить, потому что он возвращает неправильные значения "ширина" и "высота" (одинаковые для всех элементов Ad):
<xsl:key name="adnumbers" match="IE1BPBUSISM008_ITEM_OUT" use="ITEM_NUMBER"/>
....
<xsl:for-each select="E1BPBUSISM008_ITEM_OUT[generate-id(.)=generate-id(key('adnumbers',ITEM_NUMBER)[1])]">
<xsl:sort select="ITEM_NUMBER"/>
<Ad>
<ad-number>
<xsl:value-of select="ITEM_NUMBER/text()"/>
</ad-number>
<width>
<xsl:value-of select="E1BPBUSISM008_AD_SPEC_AD_OU/PLANNED_WIDTH"/>
</width>
<height>
<xsl:value-of select="E1BPBUSISM008_AD_SPEC_AD_OU/PLANNED_HEIGHT"/>
</height>
выходы:
<Ad>
<number>010</ad-number>
<width>1.851</width>
<heigth>0.000</heigth>
</Ad>
<Ad>
<number>020</ad-number>
<width>1.851</width>
<heigth>0.000</heigth>
</Ad>
1 ответ
Вам не понадобится фактическая мюнхенская группировка - использование ключа будет достаточно для получения желаемого результата.
<xsl:key name="k_AD_SPEC_AD_OU" match="E1BPBUSISM008_AD_SPEC_AD_OU" use="ITEM_NUMBER" />
<!-- ... -->
<xsl:for-each select="E1BPBUSISM008_ITEM_OUT">
<xsl:sort select="ITEM_NUMBER" />
<Ad>
<ad-number>
<xsl:value-of select="ITEM_NUMBER" />
</ad-number>
<width>
<xsl:value-of select="key('k_AD_SPEC_AD_OU', ITEM_NUMBER)[1]/PLANNED_WIDTH" />
</width>
<height>
<xsl:value-of select="key('k_AD_SPEC_AD_OU', ITEM_NUMBER)[1]/PLANNED_HEIGHT" />
</height>
</Ad>
</xsl:for-each>
<!-- ... -->
Однако правильное решение зависит от отношения между E1BPBUSISM008_ITEM_OUT
а также E1BPBUSISM008_AD_SPEC_AD_OU
Ваш пример предполагает, что это просто 1 к 1, что делает ключ ненужным, но я подозреваю, что ваше реальное отношение может быть скорее 1 к 0 или 1 или даже 1 к 0 или более.
Если вам нужно создать выход для пропавших без вести E1BPBUSISM008_AD_SPEC_AD_OU
элементы (отношение 1 к 0 или 1), xslt потребуется некоторая настройка.
Для простого отношения 1 к 1 ваш xslt может выглядеть так:
<!-- ... -->
<xsl:for-each select="E1BPBUSISM008_ITEM_OUT">
<xsl:sort select="ITEM_NUMBER" />
<Ad>
<ad-number>
<xsl:value-of select="ITEM_NUMBER" />
</ad-number>
<xsl:call-template name="AD_SPEC_AD_OU">
<xsl:with-param name="pITEM_NUMBER" select="ITEM_NUMBER" />
</xsl:call-template>
</Ad>
</xsl:for-each>
<xsl:template name="AD_SPEC_AD_OU">
<xsl:param name="pITEM_NUMBER" />
<width>
<xsl:value-of select="//E1BPBUSISM008_AD_SPEC_AD_OU[ITEM_NUMBER = $pITEM_NUMBER]/PLANNED_WIDTH" />
</width>
<height>
<xsl:value-of select="//E1BPBUSISM008_AD_SPEC_AD_OU[ITEM_NUMBER = $pITEM_NUMBER]/PLANNED_HEIGHT" />
</height>
</xsl:template>