javascript - Is there any way of getting an error message from the browsers XslProcessor object when using xsl:message terminate

时间: 2025-01-06 admin 业界

Here is what I am using:

<?xml version="1.0" encoding="utf-8"?>
<songList/>

xsl:

<xsl:stylesheet version="1.0" xmlns:xsl=";>
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:template match="/">
    <out>ROOT found</out>   
    <xsl:message terminate="yes"><xsl:value-of select="'Test message - ZZZ'"/></xsl:message>
</xsl:template>
</xsl:stylesheet>

I have an html page that calls this and when the terminate="no" (or I remove this line completely) the result is (as expected);

<out>ROOT found</out> 

The code is pretty much what is to be found in say MDN, eg

try{
    resultDoc = processor.transformToFragment(xmlDoc, document);
} catch (err) {
    console.log('err=' + err);
    return false;
}   

My issue is that whilst I am using FF and gecko, and the page here seems to indicate xsl:message is supported, it only appears to be supported in the very loosest sense, ie it halts processing but it does not pass back the error/informational message so is of limited utility. Am I doing something incorrectly? When I set a breakpoint on the console.log('err=' + err); line it is totally unpopulated. Yes, it does get hit but any error information is simply not present.

Here is what I am using:

<?xml version="1.0" encoding="utf-8"?>
<songList/>

xsl:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:template match="/">
    <out>ROOT found</out>   
    <xsl:message terminate="yes"><xsl:value-of select="'Test message - ZZZ'"/></xsl:message>
</xsl:template>
</xsl:stylesheet>

I have an html page that calls this and when the terminate="no" (or I remove this line completely) the result is (as expected);

<out>ROOT found</out> 

The code is pretty much what is to be found in say MDN, eg

try{
    resultDoc = processor.transformToFragment(xmlDoc, document);
} catch (err) {
    console.log('err=' + err);
    return false;
}   

My issue is that whilst I am using FF and gecko, and the page here https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/message#gecko_support seems to indicate xsl:message is supported, it only appears to be supported in the very loosest sense, ie it halts processing but it does not pass back the error/informational message so is of limited utility. Am I doing something incorrectly? When I set a breakpoint on the console.log('err=' + err); line it is totally unpopulated. Yes, it does get hit but any error information is simply not present.

Share Improve this question asked yesterday walburywalbury 787 bronze badges 2
  • Does resultDoc perhaps contain the error message? – Martin Honnen Commented yesterday
  • No. resultDoc remains resolutely null. My question really is aimed at establishing if there is any point (hope) in using XslProcessor object, there being little point if any error that does occur (not just a deliberate one as in this case) is just essentially unknowable. I don't know why this should be the case but it is increasingly appearing to be so. Annoying as you can do so much amazing stuff using xsl in a browser (and it is still present in all browsers) but if something does fall over and you literally have no way of knowing what it is, it's a bit of a show-stopper. – walbury Commented 17 hours ago
Add a comment  | 

1 Answer 1

Reset to default 0

If you use SaxonJS and the XPath 3.1 fn:transform function to run the transformation instead of the built-in XSLTProcessor you can access error details:

const xml = `<?xml version="1.0" encoding="utf-8"?>
<songList/>`;

const xslt = `<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:template match="/">
    <out>ROOT found</out>   
    <xsl:message terminate="yes"><xsl:value-of select="'Test message - ZZZ'"/></xsl:message>
</xsl:template>
</xsl:stylesheet>`;

var domParser = new DOMParser();

var xmlDoc = domParser.parseFromString(xml, 'application/xml');

var resultDoc = null;

try{
    resultDoc = SaxonJS.XPath.evaluate(`transform(map {
      'stylesheet-text' : $xslt,
      'source-node' : .
    })?output`, xmlDoc, { params : { xslt : xslt }});
} catch (err) {
    console.log(`${err.message} at ${err.xsltLineNr} with message ${err.errorObject.textContent}`);
}  
<script src="https://martin-honnen.github.io/SaxonJS-2.7/SaxonJS2.js"></script>

I can't tell whether it is an option for you but it is worth mentioning and doesn't fit into a comment.

If you have a static stylesheet you can precompile it to JSON with the xslt3 Node.js command line tool and use SaxonJS.transform:

    const xml = `<?xml version="1.0" encoding="utf-8"?>
    <songList/>`;

    const xsltJson = `{"N":"package","version":"10","packageVersion":"1","saxonVersion":"SaxonJS 2.7","target":"JS","targetVersion":"2","name":"TOP-LEVEL","relocatable":"true","buildDateTime":"2025-01-04T23:50:40.231+01:00","ns":"xml=~ xsl=~","C":[{"N":"co","binds":"","id":"0","C":[{"N":"mode","onNo":"TC","flags":"","patternSlots":"0","prec":"","C":[{"N":"templateRule","rank":"0","prec":"0","seq":"0","ns":"xml=~ xsl=~","minImp":"0","flags":"s","slots":"200","line":"3","module":"terminate-test1.xsl","expand-text":"false","match":"/","prio":"-0.5","matches":"ND","C":[{"N":"p.nodeTest","role":"match","test":"ND","sType":"1ND","ns":"= xml=~ xsl=~ "},{"N":"sequence","role":"action","sType":"* ","C":[{"N":"elem","name":"out","sType":"1NE nQ{}out ","nsuri":"","namespaces":"","line":"4","C":[{"N":"valueOf","sType":"1NT ","C":[{"N":"str","sType":"1AS ","val":"ROOT found"}]}]},{"N":"message","sType":"0 ","ns":"xml=~ xsl=~","C":[{"N":"valueOf","flags":"l","sType":"1NT ","role":"select","C":[{"N":"fn","name":"string-join","role":"select","C":[{"N":"first","C":[{"N":"str","val":"Test message - ZZZ","sType":"1AS","ns":"= xml=~ xsl=~ ","role":"select","line":"4"}]},{"N":"str","sType":"1AS ","val":" "}]}]},{"N":"str","sType":"1AS ","val":"true","role":"terminate"},{"N":"str","sType":"1AS ","val":"Q{http://www.w3.org/2005/xqt-errors}XTMM9000","role":"error"}]}]}]}]}]},{"N":"overridden"},{"N":"output","C":[{"N":"property","name":"Q{http://saxon.sf.net/}stylesheet-version","value":"10"},{"N":"property","name":"method","value":"xml"},{"N":"property","name":"omit-xml-declaration","value":"yes"}]},{"N":"decimalFormat"}],"Σ":"ae9aa87e"}`;

    var domParser = new DOMParser();

    var xmlDoc = domParser.parseFromString(xml, 'application/xml');

    var resultDoc = null;

    try{
        resultDoc = SaxonJS.transform({
          stylesheetText : xsltJson,
          sourceNode : xmlDoc
        }).principalResult;

    } catch (err) {
        console.log(`${err.message} at ${err.xsltLineNr} with message ${err.errorObject.textContent}`);
    }  
<script src="https://martin-honnen.github.io/SaxonJS-2.7/SaxonJS2.rt.js"></script>

SaxonJS 3.0 is currently in beta, the final release expected in the next weeks is supposed to have a compile method that you can call from your client-side code to save you the precompile step with xslt3.

最新文章