Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Catch error messages from <xsl:message terminate="yes"/> #700

Closed
christianhujer opened this issue Oct 30, 2019 · 6 comments · Fixed by #715
Closed

Catch error messages from <xsl:message terminate="yes"/> #700

christianhujer opened this issue Oct 30, 2019 · 6 comments · Fixed by #715
Labels
Milestone

Comments

@christianhujer
Copy link

christianhujer commented Oct 30, 2019

I could not find documentation for how to catch error messages from <xsl:message terminate="yes"/>. I tried to guess <x:expect/> with test="$x:result?err?message" but it seems undefined. I can workaround with test="$x:result?err?description" but that's the processor termination message, not the XSLT termination message.

Details:

My XSLT has code like this:

<?xml version="1.0"?>
<xsl:transform
    exclude-result-prefixes="html"
    version="2.0"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:html="http://www.w3.org/1999/xhtml"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xpath-default-namespace="http://www.w3.org/1999/xhtml"
>
    <xsl:template match="/">
        <xsl:for-each select="//abbr[not(@title)]">
            <xsl:choose>
                <xsl:when test="//abbr[@title]/. = current()/."/>
                <xsl:when test="document('../../data/abbrev.xml')//abbr[. = current()/.]"/>
                <xsl:otherwise>
                    <xsl:message terminate="yes">
                        <xsl:value-of select="base-uri(.)"/>
                        <xsl:text>: error: Abbreviations without title:</xsl:text>
                            <xsl:for-each select="//abbr[not(@title)]">
                                <xsl:choose>
                                    <xsl:when test="//abbr[@title]/. = current()/."/>
                                    <xsl:when test="document('../../data/abbrev.xml')//abbr[. = current()/.]"/>
                                    <xsl:otherwise><xsl:text> </xsl:text><xsl:value-of select="."/></xsl:otherwise>
                                </xsl:choose>
                            </xsl:for-each>
                    </xsl:message>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each>
    </xsl:template>

</xsl:transform>

I tried to test it like this:

<?xml version="1.0" encoding="UTF-8" ?>
<x:description
    xmlns:x="http://www.jenitennison.com/xslt/xspec"
    xmlns="http://www.w3.org/1999/xhtml"
    stylesheet="../layout.xslt"
>
    <x:scenario label="Aborts with abbreviation with no expansion" catch="yes">
        <x:context select="/">
            <abbr>AbbreviationWithoutExpansion</abbr>
        </x:context>
        <x:expect
            label="err:message"
            test="$x:result?err?description"
            select="'Abbreviation AbbreviationWithoutExpansion without title'"
        />
    </x:scenario>
</x:description>

The error message generated by <xsl:message/> is important and specified, so I would like to test whether the error message has the correct format. I could not find how to do that with XSpec.

Two workarounds are possible in my situation:

  • I could generate the message in a separate template or function to test the message. That's probably a good idea anyway, to achieve more modularity of the code.
  • I could work with the error description instead, which is Processing terminated by xsl:message at line 68 in abbrev.xslt.

As a side-note, base-uri(.) returns the empty string, I expect base-uri(.) to instead return the URI of the .xspec file.

@AirQuick
Copy link
Member

AirQuick commented Oct 31, 2019

Looks like Saxon does not work as specified by https://www.w3.org/TR/xslt-30/#element-catch :

err:value | item()* | ... For an error raised by evaluating xsl:message with terminate="yes", or a failing xsl:assert, this is the document node at the root of the tree containing the XML message body.

When I run this stylesheet,

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet exclude-result-prefixes="#all" version="3.0"
  xmlns:err="http://www.w3.org/2005/xqt-errors" xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output indent="yes" />

  <xsl:template name="xsl:initial-template">
    <xsl:try>
      <xsl:message terminate="yes">
        <test>message</test>
      </xsl:message>
      <xsl:catch>
        <err>
          <code>
            <xsl:value-of select="$err:code" />
          </code>
          <description>
            <xsl:value-of select="$err:description" />
          </description>
          <value>
            <xsl:sequence select="$err:value" />
          </value>
        </err>
      </xsl:catch>
    </xsl:try>
  </xsl:template>
</xsl:stylesheet>

<value> is empty:

C:\catch-message>java -jar "%SAXON_JAR%" -it -t -xsl:test.xsl
Saxon-HE 9.9.1.5J from Saxonica
Java version 1.8.0_231
Stylesheet compilation time: 462.3483ms
Processing  (no source document) initial template = xsl:initial-template
<test>message</test>
<?xml version="1.0" encoding="UTF-8"?>
<err>
   <code>XTMM9000</code>
   <description>Processing terminated by xsl:message at line 11 in test.xsl</description>
   <value/>
</err>

@AirQuick
Copy link
Member

As a side-note, base-uri(.) returns the empty string, I expect base-uri(.) to instead return the URI of the .xspec file.

If you write child nodes in <x:context>, a new document is created on memory for use as the context node. At the moment, you need to set @xml:base explicitly:

<x:context select="/">
    <abbr xml:base="{$x:xspec-uri}">AbbreviationWithoutExpansion</abbr>
</x:context>

Or if you use x:context/@href, the specified external document is loaded as it is and its document/base URI is kept.

@AirQuick
Copy link
Member

@Saxonica
In #700 (comment), is Saxon working as intended?

@AirQuick AirQuick added this to the v1.5.0 milestone Oct 31, 2019
@AirQuick
Copy link
Member

AirQuick commented Nov 6, 2019

Reported to saxon-help.
Acknowledged by Saxonica: https://saxonica.plan.io/issues/4376

@AirQuick
Copy link
Member

AirQuick commented Nov 9, 2019

Closed this issue because

@AirQuick
Copy link
Member

AirQuick commented Dec 7, 2019

Saxon 9.9.1.6 fixes https://saxonica.plan.io/issues/4376 and now $x:result?err?value is a document node containing a Saxon-specific processing instruction and the message body.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants