Методы обработки исключений XSLT - PullRequest
4 голосов
/ 24 сентября 2010

Начиная с XSLT 2.0, насколько я знаю (поправьте меня, если я ошибаюсь), в языке нет собственного механизма обработки исключений.

У меня есть несколько таблиц стилей, которые пытаются выполнить некоторую обработку указанных кусков входного документа, копируя все остальное без изменений. Есть редкие исключительные условия, которые я не могу легко обнаружить до того, как начну производить вывод для данного чанка. Они достаточно редки, и когда я сталкиваюсь с ними, все, что я хочу сделать, это отменить обработку этого чанка и выдать его без изменений. Нужна какая-то обработка исключений, но XSLT не очень помогает. Я не хочу, чтобы Java или другой язык были включены в эту смесь.

У меня есть работоспособное решение, описанное ниже, но меня интересуют другие подходы. У всех вас есть лучший способ сделать что-то подобное?

Вот пример сценария, о котором я говорю. Вот входной документ:

<doc>
    <block>some text, just copy.</block>
    <!-- the following table should have B substituted for a -->
    <table>
        <tr><td>a</td><td>b</td><td>c</td></tr>
        <tr><td>b</td><td>a</td><td>c</td></tr>
        <tr><td>b</td><td>c</td><td>a</td></tr>
    </table>
    <block>some more text, just copy.</block>
    <!-- the following table should be copied unaltered because of the presence of an x -->
    <table>
        <tr><td>a</td><td>b</td><td>c</td></tr>
        <tr><td>b</td><td>a</td><td>x</td></tr>
        <tr><td>b</td><td>c</td><td>a</td></tr>
    </table>
</doc>

Я хочу просмотреть каждую таблицу и заменить все значения ячеек "a" на "B". Однако если где-то в таблице есть «х», я хочу просто скопировать таблицу без изменений. Я знаю, что в этом случае я мог бы просто провести тест tr/td[.='x'] на столе, чтобы обнаружить это условие. В реальном случае, однако, не так просто заранее проверить состояние.

Вот некоторые XSLT, которые не учитывают исключение:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="table">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates mode="inner"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template mode="inner" match="td">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:choose>
                <xsl:when test=". = 'a'">
                    <xsl:value-of select="'B'"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="."/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:copy>
    </xsl:template>

    <xsl:template mode="inner" match="@*|node()" priority="-10">
        <xsl:copy>
            <xsl:apply-templates mode="inner" select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="@*|node()" priority="-10">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Вывод этого:

<doc>
    <block>some text, just copy.</block>
    <!-- the following table should have B substituted for a -->
    <table>
        <tr><td>B</td><td>b</td><td>c</td></tr>
        <tr><td>b</td><td>B</td><td>c</td></tr>
        <tr><td>b</td><td>c</td><td>B</td></tr>
    </table>
    <block>some more text, just copy.</block>
    <!-- the following table should be copied unaltered because of the presence of an x -->
    <table>
        <tr><td>B</td><td>b</td><td>c</td></tr>
        <tr><td>b</td><td>B</td><td>x</td></tr>
        <tr><td>b</td><td>c</td><td>B</td></tr>
    </table>
</doc>

Произошли замены во второй таблице, чего я не хочу.

Мое текущее решение - сделать это:

  1. Выводить каждую таблицу в переменную, а не прямо в вывод
  2. Если возникает исключение, выведите тег <EXCEPTION/>
  3. После обработки каждой таблицы просмотрите переменную для тега <EXCEPTION/>.
  4. Если возникла исключительная ситуация, скопируйте исходную таблицу, иначе скопируйте содержимое переменной.

Вот модифицированный код:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="table">
        <xsl:variable name="result">
            <xsl:copy>
                <xsl:copy-of select="@*"/>
                <xsl:apply-templates mode="inner"/>
            </xsl:copy>
        </xsl:variable>
        <xsl:choose>
            <xsl:when test="$result//EXCEPTION">
                <xsl:copy-of select="."/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy-of select="$result"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template mode="inner" match="td">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:choose>
                <xsl:when test=". = 'a'">
                    <xsl:value-of select="'B'"/>
                </xsl:when>
                <xsl:when test=". = 'x'">
                    <EXCEPTION/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="."/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:copy>
    </xsl:template>

    <xsl:template mode="inner" match="@*|node()" priority="-10">
        <xsl:copy>
            <xsl:apply-templates mode="inner" select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="@*|node()" priority="-10">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

И правильный вывод:

<doc>
    <block>some text, just copy.</block>
    <!-- the following table should have B substituted for a -->
    <table>
        <tr><td>B</td><td>b</td><td>c</td></tr>
        <tr><td>b</td><td>B</td><td>c</td></tr>
        <tr><td>b</td><td>c</td><td>B</td></tr>
    </table>
    <block>some more text, just copy.</block>
    <!-- the following table should be copied unaltered because of the presence of an x -->
    <table>
        <tr><td>a</td><td>b</td><td>c</td></tr>
        <tr><td>b</td><td>a</td><td>x</td></tr>
        <tr><td>b</td><td>c</td><td>a</td></tr>
    </table>
</doc>

Ответы [ 2 ]

1 голос
/ 25 сентября 2010

Приведенный пример очень прост и не требует каких-либо возможностей обработки исключений.

Атрибут mode - ваш друг :

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output omit-xml-declaration="yes"/>

 <xsl:template match="node()|@*" mode="#default copy">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*" mode="#current"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="table[tr/td[.='x']]">
  <xsl:apply-templates select="." mode="copy"/>
 </xsl:template>

 <xsl:template match="td/text()[.='a']">B</xsl:template>
</xsl:stylesheet>

когда это преобразование применяется к предоставленному документу XML :

<doc>
    <block>some text, just copy.</block>
    <!-- the following table should have B substituted for a -->
    <table>
        <tr><td>a</td><td>b</td><td>c</td></tr>
        <tr><td>b</td><td>a</td><td>c</td></tr>
        <tr><td>b</td><td>c</td><td>a</td></tr>
    </table>
    <block>some more text, just copy.</block>
    <!-- the following table should be copied unaltered because of the presence of an x -->
    <table>
        <tr><td>a</td><td>b</td><td>c</td></tr>
        <tr><td>b</td><td>a</td><td>x</td></tr>
        <tr><td>b</td><td>c</td><td>a</td></tr>
    </table>
</doc>

желаемый, правильный результат получается :

<doc>
    <block>some text, just copy.</block>
    <!-- the following table should have B substituted for a -->
    <table>
        <tr><td>B</td><td>b</td><td>c</td></tr>
        <tr><td>b</td><td>B</td><td>c</td></tr>
        <tr><td>b</td><td>c</td><td>B</td></tr>
    </table>
    <block>some more text, just copy.</block>
    <!-- the following table should be copied unaltered because of the presence of an x -->
    <table>
        <tr><td>a</td><td>b</td><td>c</td></tr>
        <tr><td>b</td><td>a</td><td>x</td></tr>
        <tr><td>b</td><td>c</td><td>a</td></tr>
    </table>
</doc>

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

1 голос
/ 24 сентября 2010

Если вы можете ждать XSLT 2.1 , тогда будут выражения try / catch

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...