Я пытаюсь переставить XML в несколько этапов, используя разные xsl-шаблоны, и мне удалось заставить его работать - с двумя отдельными преобразованиями xsl в последовательности. Я в настоящее время изо всех сил пытаюсь поместить 2 файла xsl в один, но потерпел неудачу. Для этого: есть ли способ использовать результат одного шаблона в другом шаблоне?
Исходный XML:
<order>
<header/>
<items>
<item no="001" material="5001" qty="4"/>
<item no="002" material="5002" qty="5"/>
<item no="P000" material="box" qty="2"/>
<item no="P001" origin_no="001" material="5001" batch="L01" qty="1"/>
<item no="P002" origin_no="001" material="5001" batch="L02" qty="3"/>
</items>
<packages>
<package id="U01">
<content item_no="P001" qty="1"/>
<content item_no="002" qty="2"/>
</package>
<package id="U02">
<content item_no="P002" qty="3"/>
<content item_no="002" qty="2"/>
</package>
<package id="U03">
<content item_no="002" qty="1"/>
</package>
</packages>
<summery/>
</order>
Этот XML содержит заказ на доставку с двумя позициями и пакетами доставки. 3. Строка с номером «P000» - это материал для помощи в упаковке. Позиции 4. и 5. - это две партии, отделенные от позиции 1..
Ссылка между обычной позицией и ее групповым разбиением является атрибутом origin_no.
Задача состоит в том, чтобы в зависимости от того, в каком пакете содержится содержимое какой позиции, сегмент пакета должен быть помещен под соответствующим элементом. В случае разделения партии: сегменты пакета должны быть помещены под исходной позицией, а не партиями.
Результат должен быть следующим:
<order>
<header/>
<items>
<item no="001" material="5001" qty="4">
<package id="U01" item_no="P001" qty="1" origin_item_no="001" batch="L01"/>
<package id="U02" item_no="P002" qty="3" origin_item_no="001" batch="L02"/>
</item>
<item no="002" material="5002" qty="5">
<package id="U01" item_no="002" qty="2"/>
<package id="U02" item_no="002" qty="2"/>
<package id="U03" item_no="002" qty="1"/>
</item>
</items>
<summery/>
</order>
Запустив следующие 2 xsl в последовательности, я мог бы успешно получить результат. Мои вопросы будут такими: есть ли элегантный способ выполнить это требование в одном сопоставлении XSLT без использования расширения exsl: node-set (которое я узнал из других публикаций)?
Первый XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="package/content">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
<xsl:variable name="v_item_no_package" select="@item_no"/>
<xsl:for-each select="../../../items/item[@no = $v_item_no_package]">
<xsl:attribute name="origin_item_no"><xsl:value-of select="@origin_no"/></xsl:attribute>
<xsl:attribute name="batch"><xsl:value-of select="@batch"/></xsl:attribute>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Второй XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="item">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
<xsl:variable name="v_no_item" select="@no"/>
<xsl:for-each select="../../packages/package/content[@origin_item_no = $v_no_item]">
<xsl:element name="package">
<xsl:copy-of select="../@id"/>
<xsl:copy-of select="./* | @*[not(.='')]"/>
</xsl:element>
</xsl:for-each>
<xsl:for-each select="../../packages/package/content[@item_no = $v_no_item]">
<xsl:element name="package">
<xsl:copy-of select="../@id"/>
<xsl:copy-of select="./* | @*[not(.='')]"/>
</xsl:element>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="packages">
</xsl:template>
<xsl:template match="items/item[starts-with(@no, 'P')]">
</xsl:template>
</xsl:stylesheet>
Большое спасибо и поздравления.