XSLT 2.0 - двухпроходная обработка

Я хотел бы понять метод двухпроходной или многоэтапной обработки и уметь применять его в моем сценарии ниже.

Я все еще нахожусь на своих тренировочных колесах XSLT - большая часть контента здесь была собрана с помощью коллег или из онлайн-источников и модифицирована в соответствии с требованиями. Пожалуйста, простите меня, если что-то непонятно или мое понимание некорректно (любые предложения по улучшению рабочих частей тоже приветствуются)

Приведенный ниже XML-код представляет собой модифицированный образец моего входного xml. Ниже показаны одна запись и интересующие узлы (плюс немного пустяков для контекста).

<root><nNumber id="N472131">
    <symbols>
        <symbol href="file:///U:/Labelling/Labels/Common Symbols/symbols with definitions/IP68_def.ai"/>
        <symbol href="file:///U:/Labelling/Labels/Common Symbols/symbols with definitions/Bin@iddef.ai"/>
        <symbol href="file:///U:/Labelling/Labels/Common Symbols/symbols with definitions/CE0197_def.ai"/>
        <symbol href="file:///U:/Labelling/Labels/Common Symbols/symbols with definitions/Recycle_def.ai"/>
        <symbol href="file:///U:/Labelling/Labels/Common Symbols/symbols with definitions/Humidity0-90_def.ai"/>
        <symbol href="file:///U:/Labelling/Labels/Common Symbols/symbols with definitions/Temp-10-55_def.ai"/>
    </symbols>
</nNumber></root>

Мой XSLT фильтрует через предоставленный параметр в @id и выполняет незначительную перестановку @id -> <id></id>

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:param name="search"></xsl:param>

<!-- Identity transform - copies all elements and attributes. -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<!-- Filter nNumber nodes by ID. -->
<xsl:template match="nNumber">
    <xsl:if test="@id=$search">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:if>
</xsl:template>

<!-- Convert the ID value from an attribute to an element under the nNumber node. -->
<xsl:template match="@id">
    <xsl:element name="{local-name(.)}">
        <xsl:value-of select="."/>
    </xsl:element>
</xsl:template>

<xsl:include href="ApplyOrder.xsl"/>

Последняя строка <xsl:include> запускает серию совпадений с тегами символов, чтобы применить предопределенное значение порядка (пример ниже).

<xsl:template match="symbol[@href='file:///U:/Labelling/Labels/Common Symbols/symbols with definitions/CE0197_def.ai']" >
    <xsl:copy>
        <xsl:attribute name="order">111</xsl:attribute><xsl:copy-of select="@*"/>
        <xsl:apply-templates/>
     </xsl:copy>
 </xsl:template>

Последний этап головоломки - упорядочить элементы символа по их значению @order (пример ниже). Я на собственном горьком опыте понял, что нельзя применить значение и отсортировать применяемое значение за одну операцию.

<symbol order="111" href="file:///U:/Labelling/Labels/Common Symbols/symbols with definitions/CE0197_def.ai"/>
<symbol order="145" href="file:///U:/Labelling/Labels/Common Symbols/symbols with definitions/IP68_def.ai"/>
<symbol order="171" href="file:///U:/Labelling/Labels/Common Symbols/symbols with definitions/Humidity0-90_def.ai"/>
<symbol order="172" href="file:///U:/Labelling/Labels/Common Symbols/symbols with definitions/Temp-10-55_def.ai"/>
<symbol order="181" href="file:///U:/Labelling/Labels/Common Symbols/symbols with definitions/Bin_2_def.ai"/>
<symbol order="191" href="file:///U:/Labelling/Labels/Common Symbols/symbols with definitions/Recycle_def.ai"/>

Итак, ниже моя попытка безупречно впихнуть пример многофазной обработки Майкла Кея в мой текущий сценарий.

У меня такое чувство, что я упускаю здесь что-то очень важное и фундаментальное - но я совершенно не понимаю, что это такое ...

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:param name="search"></xsl:param>

<!-- Identity transform - copies all elements and attributes. -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" mode="phase-1"/>
    </xsl:copy>
</xsl:template>

<!-- Filter nNumber nodes by ID. -->
<xsl:template match="nNumber">
    <xsl:if test="@id=$search">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" mode="phase-1"/>
        </xsl:copy>
    </xsl:if>
</xsl:template>

<!-- Convert the ID value from an attribute to an element under the nNumber node. -->
<xsl:template match="@id">
    <xsl:element name="{local-name(.)}">
        <xsl:value-of select="."/>
    </xsl:element>
</xsl:template>

<xsl:include href="ApplyOrder.xsl"/>

<xsl:template match="/">
    <xsl:variable name="phase-1-result">
        <xsl:apply-templates select="/" mode="phase-1"/>
    </xsl:variable>
    <xsl:apply-templates select="$phase-1-result" mode="phase-2"/>
</xsl:template>

<xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:apply-templates select="@*" mode="phase-2">
            <xsl:sort select="."/>
        </xsl:apply-templates>

        <xsl:apply-templates select="node()" mode="phase-2">
            <xsl:sort select="@order" data-type="number"/>
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

The result of the transform gives something altogether different (tags are absent, text is not from the relevant node etc..). I am happy to publish a sample if anyone thinks it will help (I'm conscious that I'm already taking up enough screen real estate)

NB. Этот рабочий процесс предназначен для публикации XML с помощью InDesign. Однако преобразование будет выполнено в Oxygen v14.


person ewan1000    schedule 15.10.2013    source источник


Ответы (1)


<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:param name="search"></xsl:param>

    <!-- Identity transform - copies all elements and attributes. -->
    <xsl:template match="@*|node()" mode="phase-1">
        <!-- ---------------------- ^^^^^^^^^^^^^^ -->
    </xsl:template>

    <!-- ... --->

    <xsl:template match="node()|@*" mode="phase-2">
        <!-- ---------------------- ^^^^^^^^^^^^^^ -->
    </xsl:template>
</xsl:stylesheet>

Примечания

  • Вы упоминаете режимы шаблонов в своем <xsl:apply-templates>, но забыли объявить их в фактических шаблонах.
  • Почему вы упорядочиваете атрибуты лексикографически по их значениям? Упорядочивание атрибутов не имеет смысла для начала. Предполагается, что это метаданные. Не упорядочивайте их, не создавайте ничего, основанного на порядке атрибутов.
person Tomalak    schedule 15.10.2013
comment
Спасибо за ваш ответ. Мое предположение заключалось в том, что применение сортировки с data-type="number" привело к числовому порядку? Есть ли альтернативный метод, который вы могли бы предложить для применения сортировки к элементам без сортируемых характеристик? - person ewan1000; 15.10.2013
comment
Я не имею в виду ту часть, которая упорядочивает элементы. Я имею в виду ту часть, которая упорядочивает атрибуты. - person Tomalak; 15.10.2013
comment
Атрибуты href относятся к изображениям, которые публикуются в определенном порядке (я не могу обойтись без этого). - person ewan1000; 15.10.2013
comment
Это все еще порядок элементов, о котором вы говорите. Я имею в виду эту часть <xsl:apply-templates select="@*" mode="phase-2"><xsl:sort select="."/></xsl:apply-templates>. - person Tomalak; 15.10.2013
comment
О, я понимаю, о чем вы говорите. Честно говоря, я использовал приведенное выше преобразование сортировки, не понимая полностью, как оно работает. Я получил ожидаемые результаты, но за два (изначально три!) Преобразования. - person ewan1000; 15.10.2013
comment
Ну как я уже сказал. Он обрабатывает атрибуты в порядке значений. Произойдет <foo x="abc" y="def" /> и <foo y="abc" x="def" />. Это не разумный поступок. - Вы не сказали мне, работает ли остальная часть ответа. - person Tomalak; 15.10.2013