Однако, когда режимы добавляются одинаково
перевод не выполнен?
Ваша проблема в этом коде :
<xsl:template match="dataset">
<UCAT>
<xsl:apply-templates mode="ucatmode"/>
</UCAT>
<DCAT>
<xsl:apply-templates mode="catmode"/>
</DCAT>
</xsl:template>
<xsl:template match="dataset" mode="ucatmode">
Инструкция выше:
<xsl:apply-templates mode="ucatmode"/>
является сокращением от;
<xsl:apply-templates select="child::node()"
mode="ucatmode"/>
Однако потомками элемента dataset
являются только элементы с именем node
и текстовые узлы только для пробелов. В вашем коде нет шаблона, который находится в режиме с именем ucatmode
и соответствует элементу node
.
Следовательно, для обработки не выбран ни один шаблон, и процессор XSLT использует встроенные шаблоны (они доступны для любого режима). Встроенные шаблоны XSLT вызывают копирование всех текстовых узлов - и это то, что вы получаете.
Точно такая же проблема существует с инструкцией :
<xsl:apply-templates mode="catmode"/>
Решение : Заменить:
<xsl:template match="dataset">
<UCAT>
<xsl:apply-templates mode="ucatmode"/>
</UCAT>
<DCAT>
<xsl:apply-templates mode="catmode"/>
</DCAT>
</xsl:template>
с
<xsl:template match="/">
<UCAT>
<xsl:apply-templates mode="ucatmode"/>
</UCAT>
<DCAT>
<xsl:apply-templates mode="catmode"/>
</DCAT>
</xsl:template>
Этот шаблон теперь соответствует узлу документа, его единственным (верхним) дочерним элементом является элемент dataset
, и теперь для обработки будут выбраны два измененных шаблона, соответствующие dataset
.
Вам все еще нужно заменить:
<xsl:apply-templates mode="catmode"/>
с:
<xsl:apply-templates mode="catmode"
select="dataset/node/desc"/>
, поскольку desc
не является потомком dataset
и встроенная обработка шаблона будет снова задействована для всех потомков dataset
, за исключением desc
.
Одно незначительное дополнительное исправление заключается в устранении всех текстовых узлов, содержащих только пробелы, - это может быть легко достигнуто с помощью следующей инструкции XSLT:
<xsl:strip-space elements="*"/>
Еще одно незначительное улучшение - предотвращение появления префикса exslt:
с каждым элементом буквального результата. Это достигается добавлением атрибута:
exclude-result-prefixes="exslt"
до <xsl:stylesheet>
инструкции.
Таким образом, полное исправленное преобразование (с соответствующим отступом для удобства чтения) составляет :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exslt="http://exslt.org/common"
exclude-result-prefixes="exslt"
>
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="nodekey" match="node/category"
use="concat(@catat,'_',@catatt)"/>
<xsl:template match="/">
<UCAT>
<xsl:apply-templates mode="ucatmode"/>
</UCAT>
<DCAT>
<xsl:apply-templates mode="catmode"
select="dataset/node/desc"/>
</DCAT>
</xsl:template>
<xsl:template match="dataset" mode="ucatmode">
<DESC>
<xsl:for-each select=
"node/category
[generate-id()
=
generate-id(key('nodekey',
concat(@catat,'_',@catatt)
)[1]
)
]">
<CAT_D>
<xsl:value-of select="concat(@catat,'_',@catatt)"/>
<xsl:text>_</xsl:text>
<xsl:value-of select="."/>
</CAT_D>
</xsl:for-each>
</DESC>
</xsl:template>
<xsl:template match="dataset/node/desc" mode="catmode">
<CATQ>
<xsl:value-of select="."/>
</CATQ>
</xsl:template>
</xsl:stylesheet>
Когда он применяется к предоставленному документу XML :
<dataset>
<node>
<category comat="0" catat="AC1" catatt="AD1">C1</category>
<desc>D1</desc>
</node>
<node>
<category comat="0" catat="AC2" catatt="AD2">C2</category>
<desc>D2</desc>
</node>
<node>
<category comat="0" catat="AC1" catatt="AD1">C1</category>
<desc>D1</desc>
</node>
<node>
<category comat="0" catat="AC3" catatt="AD3">C3</category>
<desc>D3</desc>
</node>
</dataset>
желаемый, правильный результат выдается :
<UCAT>
<DESC>
<CAT_D>AC1_AD1_C1</CAT_D>
<CAT_D>AC2_AD2_C2</CAT_D>
<CAT_D>AC3_AD3_C3</CAT_D>
</DESC>
</UCAT>
<DCAT>
<CATQ>D1</CATQ>
<CATQ>D2</CATQ>
<CATQ>D1</CATQ>
<CATQ>D3</CATQ>
</DCAT>