Есть ли способ сохранить преобразованный xml с помощью шаблона XSLT или переменной и т. д., а затем использовать его для дальнейшей обработки? Преобразованный xml будет иметь разные элементы (количество и имена), и мне нужно обработать их в одной таблице стилей, чтобы получить окончательный преобразованный XML.
Я пытаюсь решить следующую проблему.
НАЧАЛО XML
<shop>
<product>
<name />
<categorytxt> Garden > Tables > Blue </categorytxt>
</product>
<product>
<name/>
<categorytxt> Garden > Tables > Green </categorytxt>
</product>
<product>
<name />
<categorytxt> Home > Tables > Green </categorytxt>
</product>
<product>
<name />
<categorytxt> Home > Chairs > White </categorytxt>
</product>
</shop>
И мой желаемый выходной XML будет таким...
<!-- category treeview structure -->
<categories>
<category id="1" parent="root">Garden</category>
<category id="2" parent="1">Tables</category>
<category id="3" parent="2">Blue</category>
<category id="4" parent="2">Green</category>
<category id="5" parent="root">Home</category>
<category id="6" parent="5">Tables</category>
<category id="7" parent="6">Green</category>
<category id="8" parent="5">Chairs</category>
<category id="9" parent="8">White</category>
</categories>
До сих пор мне удавалось фильтровать только уникальные элементы categorytxt и разделить их на элементы категории
Но проблема заключается в том, как отфильтровать дубликаты (не может быть более одного «Дом» в результате xml и т. д.) и назначить правильный идентификатор и родительский элемент для элементов. Есть идеи, как это решить?
Это рабочий код, работающий до сих пор
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="no" method="xml" />
<xsl:template match="/">
<categories>
<xsl:for-each select="//categorytxt[not(.=../../preceding-sibling::categorytxt/product)]">
<xsl:sort select="." />
<!-- try to save it to the parameter variable whatever -->
<!-- splits each row into elements -->
<xsl:call-template name="output-tokens">
<xsl:with-param name="num" select="1" />
<xsl:with-param name="list" select="concat(. ,' > ')" />
</xsl:call-template>
</xsl:for-each>
</categories>
</xsl:template>
<xsl:template name="output-tokens">
<xsl:param name="num" />
<xsl:param name="list" />
<xsl:variable name="newlist" select="concat(normalize-space($list), ' ')" />
<xsl:variable name="first" select="substring-before($newlist, '>')" />
<xsl:variable name="remaining" select="substring-after($newlist, '>')" />
<xsl:if test="$first">
<category id="{$num}">
<xsl:copy-of select="normalize-space($first)" />
</category>
</xsl:if>
<xsl:if test="$remaining">
<xsl:call-template name="output-tokens">
<xsl:with-param name="num" select="$num + 1"/>
<xsl:with-param name="list" select="$remaining" />
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Трудно сказать, как исправить код, не видя его. Особенно когда мы даже не знаем, какую версию XSLT вы используете.
Я использую версию 1.0. И я не знаю, как xpath получить результирующие категории/категории для дальнейшей обработки
О каком процессоре XSLT 1.0 идет речь?
пока что тестировал в chrome <?xml-stylesheet href="xsl10.xsl" type="text/xsl"?>
Я имел в виду, какой процессор вы будете использовать в производстве. Перед вами стоит непростая задача, и вы могли бы воспользоваться несколькими функциями расширения, если ваш процессор их поддерживает. --- Я бы также рекомендовал вам узнать о мюнхенской группировке: jenitennison.com/xslt/grouping/muenchian.html
Спасибо, Майкл. Это также полезная информация о группировке. Теперь у меня есть шанс побороться с информацией, предоставленной вами и Мартином.
В общем, в XSLT 1, если вы создаете узлы в переменной/параметре, например.
<xsl:variable name="intermediary-result-rtf">
<foo>
<xsl:apply-templates/>
</foo>
</xsl:variable>
эта переменная имеет тип фрагмента дерева результатов, для которого стандартный/чистый XSLT 1.0 допускает только xsl:copy-of select="$intermediary-result-rtf
или xsl:value-of select="$intermediary-result-rtf"
.
Однако большинство процессоров XSLT 1.0 поддерживают функцию расширения (в проприетарном пространстве имен или в пространстве имен EXSLT http://exslt.org/common
) для преобразования фрагмента результирующего дерева в набор узлов, например.
<xsl:variable name="intermediary-result"
select="exsl:node-set($intermediary-result-rtf)"
xmlns:exsl="http://exslt.org/common"/>
затем вы можете выбрать, например. $intermediary-result/foo
, то есть делать выбор XPath в наборе узлов.
Это хорошая отправная точка. Спасибо.
Да, вы можете хранить XML, созданный вашим преобразованием, внутри переменной и ссылаться на него в последующих шагах. Что касается вашей логики для желаемого результата, на самом деле неясно, как ваш ввод преобразуется в заявленный результат.