XSLT异常处理技术

从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’.但是,如果表格中有某个’x’,我只想复制未经修改的表格.我知道在这种情况下,我可以在表上进行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>

它在第二个表中进行了替换,这是我不想要的.

我目前的解决方案是这样做:

>将每个表发送到变量而不是直接输入到输出中
>如果发生异常,则发出< EXCEPTION />标签
>处理完每个表后,查看< EXCEPTION />的变量.标签.
>如果发生异常,请复制原始表,否则复制变量的内容.

这是修改后的代码:

<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>

最佳答案 如果你可以等待
XSLT 2.1,那么将有try / catch表达式

点赞