Page 1 of 1

Variable definition not processed when variable isn't output

Posted: Thu Sep 28, 2017 12:25 am
by mboudreau
I was setting up a stylesheet in which I expected to use a number of variables. Two of my variable definitions were as follows:

Code: Select all


<xsl:variable name="doi">
<xsl:choose>
<xsl:when test="/article/front/article-meta/article-id[@pub-id-type = 'doi']">
<xsl:value-of select="/article/front/article-meta/article-id[@pub-id-type = 'doi']"/>
</xsl:when>
<xsl:otherwise>
<xsl:message>ERROR: Cannot find DOI</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>

<xsl:variable name="doi-suffix">
<xsl:value-of select="replace($doi, '^10.[0-9]+/', '')"/>
</xsl:variable>
When I ran the transformation on a file that I knew was missing the expected <article-id> element, I was surprised not to see the error message appear. Eventually I discovered that when neither the 'doi' nor the 'doi-suffix' variable was used in any of my templates, the variable definitions seemed not to be processed at all. When I added either variable to the output of any template, things worked as expected again.

I don't know if this is a characteristic of Saxon (my transformation is using the SaxonPE-9.6.0.7 processor) or Oxygen (version 18.1), but it feels buggy.

Re: Variable definition not processed when variable isn't output

Posted: Thu Sep 28, 2017 9:53 am
by Radu
Hi,

I'm not sure what you mean by this:
but it feels buggy
You defined two variables but you did not use them anywhere. So of course they produced no effect on the output. That's how the XSLT standard works.
Also if you have an xsl:value pointing to some non existing XPath:

Code: Select all

<xsl:value-of select="/nonExistingElement"/>
the processing will not break. The value returned in this case will be empty. Again, that's how the XSLT standard works and the Saxon processor which is used by Oxygen to transform XML documents using XSLT implements the standard.

Regards,
Radu

Re: Variable definition not processed when variable isn't output

Posted: Wed Jun 06, 2018 10:12 pm
by mboudreau
Hi,

I'd like to pick this topic up again to ask what's the best practice when you need to set a variable and you also need to know if the variable has unexpectedly not been set?

In this case, I'm processing JATS XML files that may or may not have a <volume> element. So my stylesheet has this at the top level:

Code: Select all


    <xsl:variable name="volume">
<xsl:choose>
<xsl:when test="/article/front/article-meta/volume">
<xsl:value-of select="normalize-space(/article/front/article-meta/volume)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="string('')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
Then in the template for my root element, I test the variable itself:

Code: Select all


    <xsl:template match="article">

<xsl:if test="string($volume) = ''">
<xsl:message>
<xsl:text>MS </xsl:text>
<xsl:value-of select="$msid"/>
<xsl:text>: cannot find volume</xsl:text>
</xsl:message>
</xsl:if>

<xsl:text disable-output-escaping="yes"><![CDATA[<!DOCTYPE article PUBLIC "-//NLM//DTD Journal Publishing DTD v3.0 20080202//EN" "journalpublishing3.dtd">]]>
</xsl:text>
<article article-type="{$article-type}" dtd-version="3.0" xml:lang="en"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:mml="http://www.w3.org/1998/Math/MathML"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:atict="http://www.arbortext.com/namespace/atict">
<xsl:apply-templates select="front"/>
</article>
</xsl:template>
I first tried just a simple test="not($volume)", but that didn't generate my error message, so I'm testing its string value instead.

Is there a simpler, better way of doing this?

Re: Variable definition not processed when variable isn't output

Posted: Thu Jun 07, 2018 9:34 am
by Radu
Hi,

Maybe if you remove the "<xsl:otherwise>" from inside the variable declaration the not($volume) will work as expected.

Regards,
Radu

Re: Variable definition not processed when variable isn't output

Posted: Thu Jun 07, 2018 5:31 pm
by mboudreau
Removing the <xsl:otherwise> element doesn't help.

However, it appears that "string($volume) = ''" and "not(string($volume))" both work as a test for the undefined variable.