Вот краткое и простое решение, которое переопределяет правило / шаблон идентификации:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kItemByCode" match="ITEM"
use="ITEMCODE"/>
<xsl:key name="kActionByCode" match="ACTION"
use="../ITEMCODE"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"ITEM[not(generate-id() =
generate-id(key('kItemByCode', ITEMCODE)[1])
)
]"/>
<xsl:template match=
"ITEM[generate-id() =
generate-id(key('kItemByCode', ITEMCODE)[1])
and
key('kActionByCode', ITEMCODE) = 'ADD'
and
key('kActionByCode', ITEMCODE) = 'DELETE'
]
/ACTION/text()
">
<xsl:text>UPDATE</xsl:text>
</xsl:template>
<xsl:template match=
"ITEM[generate-id() =
generate-id(key('kItemByCode', ITEMCODE)[1])
and
key('kActionByCode', ITEMCODE) = 'ADD'
and
key('kActionByCode', ITEMCODE) = 'DELETE'
]
/OLDSINO
">
<OLDSINO>
<xsl:apply-templates mode="List"
select="key('kItemByCode', ../ITEMCODE)[position()>1]" />
</OLDSINO>
</xsl:template>
<xsl:template match="ITEM" mode="List">
<xsl:if test="not(position()=1)">,</xsl:if>
<xsl:value-of select="SINO"/>
</xsl:template>
</xsl:stylesheet>
, когда это преобразование применяется к следующему документу XML (на основании и исправлении предоставленного сильно искаженного фрагмента XML):
<t>
<ITEM>
<SINO>1</SINO>
<ITEMCODE>101</ITEMCODE>
<ACTION>ADD</ACTION>
<OLDSINO></OLDSINO>
</ITEM>
<ITEM>
<SINO>2</SINO>
<ITEMCODE>101</ITEMCODE>
<ACTION>DELETE</ACTION>
<OLDSINO></OLDSINO>
</ITEM>
<ITEM>
<SINO>3</SINO>
<ITEMCODE>102</ITEMCODE>
<ACTION>ADD</ACTION>
<OLDSINO></OLDSINO>
</ITEM>
<ITEM>
<SINO>4</SINO>
<ITEMCODE>103</ITEMCODE>
<ACTION>ADD</ACTION>
<OLDSINO></OLDSINO>
</ITEM>
<ITEM>
<SINO>5</SINO>
<ITEMCODE>103</ITEMCODE>
<ACTION>DELETE</ACTION>
<OLDSINO></OLDSINO>
</ITEM>
<ITEM>
<SINO>6</SINO>
<ITEMCODE>104</ITEMCODE>
<ACTION>DELETE</ACTION>
<OLDSINO></OLDSINO>
</ITEM>
</t>
желаемый, правильный результат:
<t>
<ITEM>
<SINO>1</SINO>
<ITEMCODE>101</ITEMCODE>
<ACTION>UPDATE</ACTION>
<OLDSINO>2</OLDSINO>
</ITEM>
<ITEM>
<SINO>3</SINO>
<ITEMCODE>102</ITEMCODE>
<ACTION>ADD</ACTION>
<OLDSINO />
</ITEM>
<ITEM>
<SINO>4</SINO>
<ITEMCODE>103</ITEMCODE>
<ACTION>UPDATE</ACTION>
<OLDSINO>5</OLDSINO>
</ITEM>
<ITEM>
<SINO>6</SINO>
<ITEMCODE>104</ITEMCODE>
<ACTION>DELETE</ACTION>
<OLDSINO />
</ITEM>
</t>
Объяснение :
Правило / шаблон идентификации копирует каждый узел "как есть".
Шаблон с пустым телом переопределяет правило идентификации длякаждый не первый ITEM
из группы ITEM
элементов с одинаковым ITEMCODE
- ни один такой узел не копируется в вывод (он же удален).
Третий шаблон переопределяет правило идентификации для каждого элемента ITEM
, который является первым в группе из ITEM
элементов с таким же ITEMCODE
и для которого ITEMCODE
существуют элементы с ACTION
и «ADD», и «УДАЛЯТЬ".Он создает необходимый элемент OLDSINO
, применяя шаблоны в режиме «Список» ко всем ITEM
элементам в группе, кроме первого.
Метод Мюнхена для группировки и вообщеключи используются для достижения эффективной и компактной реализации.
Это решение корректно работает с любой произвольной смесью ITEM
элементов, которые могут иметь одинаковые ITEMCODE
.