Skip to main content
1-Visitor
January 6, 2010
Question

Lost Variable Inheritance - why?

  • January 6, 2010
  • 8 replies
  • 1477 views

I'm tracking down problems with using the Army LOGSA v1.5 XML stylesheets in Arbortext 5.4 M020.

I've tracked down a problem with the PE crashing on the tables stylesheet to a lack of an inherited table value. This happens in a couple of places with a couple different variables (rowsep and colsep that I know of so far).

Can any of you see why $rowsep is losing its inherited value? The workaround at the moment is to give every single row a rowsep (ditto with colsep). Setting it in the table tag is not sufficient.

Here is where it dies if rowsep = " with the error "Cannot convert string " to a double":

<xsl:if test="(($frame" ==" 'all'=" or=" $frame="topbot" or=" $frame="bottom" )=" and=" $lastrow="0)" or=" <b=">$rowsep!=0">

Here's the code fragment that sets $rowsep followed by inherited.table.attribute template followed by get-attribute template

<xsl:variable name="&lt;b">rowsep">
<xsl:call-template name="inherited.table.attribute">
<xsl:with-param name="entry" select="."> </xsl:with-param>
<xsl:with-param name="colnum" select="$entry.colnum"> </xsl:with-param>
<xsl:with-param name="attribute" select="&lt;b">rowsep"> </xsl:with-param>
</xsl:call-template>
</xsl:variable>


<xsl:template name="inherited.table.attribute">
<xsl:param name="entry" select="."> </xsl:param>
<xsl:param name="colnum" select="0"> </xsl:param>
<xsl:param name="attribute" select="colsep"> </xsl:param>
<xsl:variable name="entry.value">
<xsl:call-template name="get-attribute">
<xsl:with-param name="element" select="$entry"> </xsl:with-param>
<xsl:with-param name="attribute" select="$attribute"> </xsl:with-param>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="row.value">
<xsl:call-template name="get-attribute">
<xsl:with-param name="element" select="$entry/ancestor::row[1]"> </xsl:with-param>
<xsl:with-param name="attribute" select="$attribute"> </xsl:with-param>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="span.value">
<xsl:if test="$entry/@spanname">
<xsl:variable name="spanname" select="$entry/@spanname"> </xsl:variable>
<xsl:variable name="spanspec" select="$entry/ancestor::tgroup/spanspec[@spanname=$spanname]"> </xsl:variable>
<xsl:variable name="span.colspec" select="$entry/ancestor::tgroup/colspec[@colname=$spanspec/@namest]"> </xsl:variable>
<xsl:variable name="spanspec.value">
<xsl:call-template name="get-attribute">
<xsl:with-param name="element" select="$spanspec"> </xsl:with-param>
<xsl:with-param name="attribute" select="$attribute"> </xsl:with-param>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="scolspec.value">
<xsl:call-template name="get-attribute">
<xsl:with-param name="element" select="$span.colspec"> </xsl:with-param>
<xsl:with-param name="attribute" select="$attribute"> </xsl:with-param>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$spanspec.value" !=" &quot;=">
<xsl:value-of select="$spanspec.value"/">
</xsl:when>
<xsl:when test="$scolspec.value" !=" &quot;=">
<xsl:value-of select="$scolspec.value"/">
</xsl:when>
<xsl:otherwise> </xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:variable>
<xsl:variable name="namest.value">
<xsl:if test="$entry/@namest">
<xsl:variable name="namest" select="$entry/@namest"> </xsl:variable>
<xsl:variable name="colspec" select="$entry/ancestor::tgroup/colspec[@colname=$namest]"> </xsl:variable>
<xsl:variable name="namest.value">
<xsl:call-template name="get-attribute">
<xsl:with-param name="element" select="$colspec"> </xsl:with-param>
<xsl:with-param name="attribute" select="$attribute"> </xsl:with-param>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$namest.value">
<xsl:value-of select="$namest.value"/">
</xsl:when>
<xsl:otherwise> </xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:variable>
<xsl:variable name="tgroup.value">
<xsl:call-template name="get-attribute">
<xsl:with-param name="element" select="$entry/ancestor::tgroup[1]"> </xsl:with-param>
<xsl:with-param name="attribute" select="$attribute"> </xsl:with-param>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$entry.value" !=" &quot;=">
<xsl:value-of select="$entry.value"/">
</xsl:when>
<xsl:when test="$row.value" !=" &quot;=">
<xsl:value-of select="$row.value"/">
</xsl:when>
<xsl:when test="$span.value" !=" &quot;=">
<xsl:value-of select="$span.value"/">
</xsl:when>
<xsl:when test="$namest.value" !=" &quot;=">
<xsl:value-of select="$namest.value"/">
</xsl:when>
<xsl:when test="$colnum"> 0">
<xsl:variable name="calc.colvalue">
<xsl:call-template name="colnum.colspec">
<xsl:with-param name="colnum" select="$colnum"> </xsl:with-param>
<xsl:with-param name="attribute" select="$attribute"> </xsl:with-param>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$calc.colvalue" !=" &quot;=">
<xsl:value-of select="$calc.colvalue"/">
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$tgroup.value"/">
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$tgroup.value"/">
</xsl:otherwise>
</xsl:choose>
</xsl:template>


<xsl:template name="get-attribute">
<xsl:param name="element" select="."> </xsl:param>
<xsl:param name="attribute" select=""> </xsl:param>
<xsl:for-each select="$element/@*">
<xsl:if test="local-name(.)" ==" $attribute&quot;=">
<xsl:value-of select="."/">
</xsl:if>
</xsl:for-each>
</xsl:template>

===== END CODE snippet =====

    8 replies

    1-Visitor
    January 6, 2010
    John,

    This stylesheet doesn't look for rowsep on the table tag, so try
    setting the rowsep attribute on the tgroup tag, instead.

    As a side note, to the list as a whole, I believe PE throwing an error
    in this case is not compliant with the XPath/XSLT standard. This
    would be coming from Saxon, right? I find that kind of surprising...

    -Brandon Smiley Happy

    Brandon Ibach
    Developer, Single-Sourcing Solutions, Inc.

    On Wed, Jan 6, 2010 at 10:25 AM, John Jarrett
    <-> wrote:
    > I'm tracking down problems with using the Army LOGSA v1.5 XML stylesheets in
    > Arbortext 5.4 M020.
    >
    > I've tracked down a problem with the PE crashing on the tables stylesheet to
    > a lack of an inherited table value. This happens in a couple of places with
    > a couple different variables (rowsep and colsep that I know of so far).
    >
    > Can any of you see why $rowsep is losing its inherited value? The
    > workaround at the moment is to give every single row a rowsep (ditto with
    > colsep). Setting it in the table tag is not sufficient.
    >
    > Here is where it dies if rowsep = " with the error "Cannot convert string
    > " to a double":
    >
    > <xsl:if test="(($frame" ==" 'all'=" or=" $frame="topbot" or=" $frame="bottom" )<br="/>> and $lastrow=0) or $rowsep!=0">
    >
    > Here's the code fragment that sets $rowsep followed by
    > inherited.table.attribute template followed by get-attribute template
    >
    > <xsl:variable name="rowsep">
    > <xsl:call-template name="inherited.table.attribute">
    > <xsl:with-param name="entry" select="."> </xsl:with-param>
    > <xsl:with-param name="colnum" select="$entry.colnum">
    > </xsl:with-param>
    > <xsl:with-param name="attribute" select="rowsep">
    > </xsl:with-param>
    > </xsl:call-template>
    > </xsl:variable>
    >
    >
    >
    > <xsl:template name="inherited.table.attribute">
    > <xslSmiley Tonguearam name="entry" select="."> </xslSmiley Tonguearam>
    > <xslSmiley Tonguearam name="colnum" select="0"> </xslSmiley Tonguearam>
    > <xslSmiley Tonguearam name="attribute" select="colsep"> </xslSmiley Tonguearam>
    > <xsl:variable name="entry.value">
    > <xsl:call-template name="get-attribute">
    > <xsl:with-param name="element" select="$entry">
    > </xsl:with-param>
    > <xsl:with-param name="attribute" select="$attribute">
    > </xsl:with-param>
    > </xsl:call-template>
    > </xsl:variable>
    > <xsl:variable name="row.value">
    > <xsl:call-template name="get-attribute">
    > <xsl:with-param name="element"&lt;br"/>> select="$entry/ancestor::row[1]"> </xsl:with-param>
    > <xsl:with-param name="attribute" select="$attribute">
    > </xsl:with-param>
    > </xsl:call-template>
    > </xsl:variable>
    > <xsl:variable name="span.value">
    > <xsl:if test="$entry/@spanname">
    > <xsl:variable name="spanname" select="$entry/@spanname">
    > </xsl:variable>
    > <xsl:variable name="spanspec"&lt;br"/>> select="$entry/ancestor::tgroup/spanspec[@spanname=$spanname]">
    > </xsl:variable>
    > <xsl:variable name="span.colspec"&lt;br"/>> select="$entry/ancestor::tgroup/colspec[@colname=$spanspec/@namest]">
    > </xsl:variable>
    > <xsl:variable name="spanspec.value">
    > <xsl:call-template name="get-attribute">
    > <xsl:with-param name="element" select="$spanspec">
    > </xsl:with-param>
    > <xsl:with-param name="attribute"&lt;br"/>> select="$attribute"> </xsl:with-param>
    > </xsl:call-template>
    > </xsl:variable>
    > <xsl:variable name="scolspec.value">
    > <xsl:call-template name="get-attribute">
    > <xsl:with-param name="element"&lt;br"/>> select="$span.colspec"> </xsl:with-param>
    > <xsl:with-param name="attribute"&lt;br"/>> select="$attribute"> </xsl:with-param>
    > </xsl:call-template>
    > </xsl:variable>
    > <xsl:choose>
    > <xsl:when test="$spanspec.value" !=" &quot;=">
    > <xsl:value-of select="$spanspec.value"/">
    > </xsl:when>
    > <xsl:when test="$scolspec.value" !=" &quot;=">
    > <xsl:value-of select="$scolspec.value"/">
    > </xsl:when>
    > <xslSmiley Surprisedtherwise> </xslSmiley Surprisedtherwise>
    > </xsl:choose>
    > </xsl:if>
    > </xsl:variable>
    > <xsl:variable name="namest.value">
    > <xsl:if test="$entry/@namest">
    > <xsl:variable name="namest" select="$entry/@namest">
    > </xsl:variable>
    > <xsl:variable name="colspec"&lt;br"/>> select="$entry/ancestor::tgroup/colspec[@colname=$namest]"> </xsl:variable>
    > <xsl:variable name="namest.value">
    > <xsl:call-template name="get-attribute">
    > <xsl:with-param name="element" select="$colspec">
    > </xsl:with-param>
    > <xsl:with-param name="attribute"&lt;br"/>> select="$attribute"> </xsl:with-param>
    > </xsl:call-template>
    > </xsl:variable>
    > <xsl:choose>
    > <xsl:when test="$namest.value">
    > <xsl:value-of select="$namest.value"/">
    > </xsl:when>
    > <xslSmiley Surprisedtherwise> </xslSmiley Surprisedtherwise>
    > </xsl:choose>
    > </xsl:if>
    > </xsl:variable>
    > <xsl:variable name="tgroup.value">
    > <xsl:call-template name="get-attribute">
    > <xsl:with-param name="element"&lt;br"/>> select="$entry/ancestor::tgroup[1]"> </xsl:with-param>
    > <xsl:with-param name="attribute" select="$attribute">
    > </xsl:with-param>
    > </xsl:call-template>
    > </xsl:variable>
    > <xsl:choose>
    > <xsl:when test="$entry.value" !=" &quot;=">
    > <xsl:value-of select="$entry.value"/">
    > </xsl:when>
    > <xsl:when test="$row.value" !=" &quot;=">
    > <xsl:value-of select="$row.value"/">
    > </xsl:when>
    > <xsl:when test="$span.value" !=" &quot;=">
    > <xsl:value-of select="$span.value"/">
    > </xsl:when>
    > <xsl:when test="$namest.value" !=" &quot;=">
    > <xsl:value-of select="$namest.value"/">
    > </xsl:when>
    > <xsl:when test="$colnum"> 0">
    > <xsl:variable name="calc.colvalue">
    > <xsl:call-template name="colnum.colspec">
    > <xsl:with-param name="colnum" select="$colnum">
    > </xsl:with-param>
    > <xsl:with-param name="attribute"&lt;br"/>> select="$attribute"> </xsl:with-param>
    > </xsl:call-template>
    > </xsl:variable>
    > <xsl:choose>
    > <xsl:when test="$calc.colvalue" !=" &quot;=">
    > <xsl:value-of select="$calc.colvalue"/">
    > </xsl:when>
    > <xslSmiley Surprisedtherwise>
    > <xsl:value-of select="$tgroup.value"/">
    > </xslSmiley Surprisedtherwise>
    > </xsl:choose>
    > </xsl:when>
    > <xslSmiley Surprisedtherwise>
    > <xsl:value-of select="$tgroup.value"/">
    > </xslSmiley Surprisedtherwise>
    > </xsl:choose>
    > </xsl:template>
    >
    >
    > <xsl:template name="get-attribute">
    > <xslSmiley Tonguearam name="element" select="."> </xslSmiley Tonguearam>
    > <xslSmiley Tonguearam name="attribute" select=""> </xslSmiley Tonguearam>
    > <xsl:for-each select="$element/@*">
    > <xsl:if test="local-name(.)" ==" $attribute&quot;=">
    > <xsl:value-of select="."/">
    > </xsl:if>
    > </xsl:for-each>
    > </xsl:template>
    >
    > ===== END CODE snippet =====
    >
    > -----End Original Message-----
    1-Visitor
    January 6, 2010
    On a quick look I think the problem is as you state, however the $rowsep is being set it is not finding a value, so in the test you are trying to compare to a number something that isn't or can't be changed. Probably need a test ahead of this to say if rowsep = '' then skip or do something else. ..dan --------------------------------------------------------------------------- Danny Vint Specializing in Panoramic Images
    1-Visitor
    January 6, 2010
    Hey, Dan...

    This is where I think the XSLT processor is not behaving correctly.
    If the value of $rowsep is the empty string, or otherwise not a valid
    number format, then the XPath 1.0 spec says that the result of
    converting it to a number is the special value "Not a Number" (NaN).
    NaN, by definition, is not equal to anything (including itself), so
    the "$rowsep!=0" comparison should return true without an error.

    Like I said, if Saxon is processing the transform, which I believe
    should be the case, I'm surprised, as I think it's generally pretty
    good about standards compliance. *shrug*

    All that said, changing " $rowsep!=0 " to " $rowsep!='0' " or even "
    normalize-space($rowsep)!='0' " would probably sidestep this
    unfortunate behavior on the part of the XSLT processor.

    -Brandon 🙂

    18-Opal
    January 6, 2010
    Hi Brandon--

    You're right, I think this is a standards compliance issue (and it is surprising to see it in Saxon). Then again, this behavior probably makes debugging stylesheets a lot easier. It's hard to think of a situation where trying to convert " to a number would *not* indicate some kind of stylesheet bug.

    Your fixes should work, but I thought I'd point out that they make an assumption: that an empty string value for rowsep should be treated as different from 0, i.e. wanting a row separator. In at least some cases, it seems more natural to treat the empty string as equivalent to 0, i.e. no separator. In that case, you'd want something more like this in place of ($rowsep!=0):

    (normalize-space($rowsep)!='' and normalize-space($rowsep)!='0')

    Even better would be a change to the inherited.table.attribute template to provide a default if there are absolutely no rowsep attrs anywhere in the table hierarchy. For example add a stylesheet parameter to set the rowsep default and then use it if the tgroup.value (and all the others) are empty:

    <xsl:param name="rowsep.default">0</xsl:param>

    ...

    <xsl:template name="inherited.table.attribute">
    ...
    <xsl:choose>
    ....
    <xsl:when test="$tgroup.value" !=" &quot;=">
    <xsl:value-of select="$tgroup.value"/">
    </xsl:when>
    <xsl:otherwise>
    <xsl:value-of select="$rowsep.default"/">
    </xsl:otherwise>
    <xsl:choose>
    </xsl:template>

    --Clay
    1-Visitor
    January 6, 2010
    Why do you say saxon? is PE using saxon in here somewhere? I use saxon on a lot of standalone projects, it seems to me I have seen the error before and I don't think it was from PE. Anyway I think we have a stylesheet built with one processor but not working on another. ..dan --------------------------------------------------------------------------- Danny Vint Specializing in Panoramic Images
    1-Visitor
    January 6, 2010
    Hey, Clay...

    True, it could make debugging somewhat easier, though it may be
    somewhat unintuitive for $rowsep=0 to throw an error when $rowsep='0'
    would not, given XPath's weakly-typed, convert-on-the-fly nature.
    *shrug*

    Just saw Dan's reply about Saxon... Dan, I believe Saxon is the
    default engine that is currently bundled with both Editor and PE for
    XSLT transforms.

    My fixes were intended to preserve the semantics of the existing
    transform, which appears to be compliant with the CALS table semantics
    that row separators are on by default unless specified otherwise in
    the markup or a "stylesheet" (an intentionally vague concept in the
    semantics, as I recall).

    Changes to the inherited.table.attribute template must be made with
    care, as it handles a bunch of different attributes, so providing a
    default for rowsep would require checking to make sure the current
    call is looking for that particular attribute.

    Interestingly, that template looks much like a same-named one in Norm
    Walsh's Docbook stylesheets, though the latest version of those has a
    somewhat more sophisticated version that checks for values on tbody
    and table, as well as providing the CALS-compliant defaults for rowsep
    and colsep. Incorporating some of these changes would probably
    resolve this issue, as well.

    -Brandon 🙂

    1-Visitor
    January 6, 2010
    Thanks guys!

    a. SAXParse is what is throwing the error - or, more precisely, that is what is reporting it to me via the PE.

    b. Changing $rowsep=0 to $rowsep='0' did work

    c. Setting rowsep and colsep for the tgroup also worked - although, unlike the table tag attributes, the writer can't see them - nor the poor soul composing the thousand files into one and chasing down all the errors!

    So I'll leave "b" in place for now and save the fuller fixes y'all suggested until after I run down the dozen other errors it is still throwing. Like the tables now print BUT with File | Print Composed the graphics are in table cells but the cells bound the text, not the graphic, so the graphics are all over the place...and under File | Compose | PDF the graphics don't print at all - oh, wait, that one isn't one of the errors Saxon is throwing *sigh*

    Appreciate the help very much - maybe next week I'll be able to print enough to show the Army that we really are working on their manual!

    John T. Jarrett CDT
    Tech Writer II, Tech Pubs, Integrated Logistics Support,Land & Armaments/Global Tactical Systems

    T832.673.2147 ext 1147 | M 512.736.7031 | -
    BAE Systems, 5000 I-10 West, Sealy, Texas USA 77474
    www.baesystems.com


    1-Visitor
    January 7, 2010
    At 01:44 PM 1/6/2010, you wrote:
    >Just saw Dan's reply about Saxon... Dan, I believe Saxon is the
    >default engine that is currently bundled with both Editor and PE for
    >XSLT transforms.

    I'm stuck with FOSIs so I've never seen PE in action with XSL
    ---------------------------------------------------------------------------
    Danny Vint

    Panoramic Photography