Я бы предположил, что ваш вход XML имеет узел root
, который обертывает все это, чтобы создать хорошо сформированный документ. Я также предполагаю, что все allocelement
написаны правильно (у вас есть некоторые слова как alloclement
). Я также предполагаю, что вы хотите удалить дубликаты, идентифицированные именем тега и его текстовым значением.
С XSLT 1.0:
<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="code" match="allocelement/code" use="."/>
<xsl:key name="code-sibling"
match="allocelement/*[name() != 'code']"
use="concat(parent::*/code, '|', name(), '|', .)"/>
<xsl:template match="@* | node()" name="copy">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="root/allocelement[1]"/>
</xsl:template>
<xsl:template match="allocelement">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates
select="(. | following-sibling::allocelement)/code
[generate-id() = generate-id(key('code', .)[1])]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="code">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:value-of select="."/>
<xsl:apply-templates
select="key('code', .)/(preceding-sibling::* | following-sibling::*)
[generate-id() =
generate-id(key('code-sibling', concat(parent::*/code, '|', name(), '|', .))[1])]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
при нанесении:
<root>
<allocelement>
<hd1>12</hd1>
<hd2>14</hd2>
<hd3>87</hd3>
<alc>1</alc>
<amount>4587</amount>
<code>1111</code>
</allocelement>
<allocelement>
<hd1>12</hd1>
<hd2>14</hd2>
<hd3>87</hd3>
<alc>2</alc>
<amount>80000</amount>
<code>1111</code>
</allocelement>
<allocelement>
<hd1>875</hd1>
<hd2>455</hd2>
<hd3>455</hd3>
<alc>2</alc>
<amount>80000</amount>
<code>1112</code>
</allocelement>
</root>
производит:
<root>
<allocelement>
<code>1111<hd1>12</hd1>
<hd2>14</hd2>
<hd3>87</hd3>
<alc>1</alc>
<amount>4587</amount>
<alc>2</alc>
<amount>80000</amount>
</code>
<code>1112<hd1>875</hd1>
<hd2>455</hd2>
<hd3>455</hd3>
<alc>2</alc>
<amount>80000</amount>
</code>
</allocelement>
</root>
Вот как это работает. По умолчанию используется маршрут identity transform. Сначала мы прерываем allocelement
и отправляем трансляцию по другому маршруту. Мы разрешаем ему копировать уникальный элемент code
(уникальность, идентифицируемую текстовым значением элемента), с его значением, а затем применять шаблоны для всех предыдущих/следующих братьев и сестер всех узлов code
, имеющих одинаковое значение. Теперь они будут дочерними узлами узла code
. Затем мы вызываем преобразование идентичности для тех родственных братьев, которые являются единственными (относятся к code
того же значения, имеют одно и то же имя и одно и то же текстовое значение).
1 примечание. MIXED content никогда не является хорошей идеей. Посмотрите, действительно ли вам нужно смешать текстовое значение и дочерние узлы под номером code
.
С XSLT 2.0 вы могли бы остаться в стороне от generate-id()
с:
<xsl:template match="allocelement">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:for-each-group select="(. | following-sibling::allocelement)/code" group-by=".">
<xsl:apply-templates select="."/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="code">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:value-of select="."/>
<xsl:for-each-group select="key('code', .)/(preceding-sibling::* | following-sibling::*)"
group-by="concat(parent::*/code, '|', name(), '|', .)">
<xsl:apply-templates select="."/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
Пожалуйста, после того, что вы делали до сих пор в XSLT. – toniedzwiedz