V.14.1 still crashes on invalid XSLT

The bug I wrote about some time ago with invalid XSLT still exists in v.14.1

That time it was missing the <tbody> in a <table>. This time it was an <input> inside a <tr>. Obviously wrong, I know, but apparently whichever version it was written in back in 2010/2011 allowed it and today, when I wanted to do an edit, the editor crashed.

The <input> was moved to the <td> within the <tr>.

Advertisements

Lansa Editor still rewrites my code

A follow-up to the other post from last year, I have now experienced this in a new and disturbing way.

I realize that this code is not pretty but it was just a quick job that I would fix later. In this case, I added some javascript that would append an HTML element with an attribute. The javascript used double-pings (“) and the attribute would then use pings (‘):

2017-02-14_090415

Unfortunately, when checking in the changes the Lansa Editor changed the pings to double-pings, rendering my code buggy.

Lansa Editor rewriting my code

This happened in v.12.5 and continues to happen in v.14: When I write XSLT I may write something that is perfectly valid and correct (at least, most of the time) and which produces no errors.

But then, when I reload the command handler the next day, I am not getting the same code. The Lansa Editor has rewritten my code to something else that is perfectly valid and correct (and indented differently) but which the Lansa Editor now reports an error in.

Without a doubt this is an error that comes from the rewriting and now, everytime I save, compile or check-in, I see this:

xsltparsing.png

It happens when I have used <![CDATA[ … ]]> and <xsl:text disable-output-escaping=”yes”> … </xsl:text>. The Lansa Editor removes the <![CDATA[ … ]]> and replaces the characters with the proper entities, but chokes on it itself.

A bug in the editor

It turns out that the error I got trying to access the XSLT source (not the missing shortcut, the crash) was due to a bug in the editor. I had a

<table>
<xsl:choose>
...

with no <tbody>. Yes, I know.

But the editor checked the XSLT and appears to think it is fine. Then the renderer took over and crashed, due to the missing <tbody>.

Fortunately I found the XSLT in the temp cache so with the supplier’s help I could regenerate the XSLT (deleting all my work) and reinsert my code, now with the <tbody> tag.

Done.

XSLT cheatsheet

<xsl:value-of select="key('field-value', 'EANTAL')" />

<xsl:element name="input">
 <xsl:attribute name="id">AKTEST2</xsl:attribute>

<xsl:if test="/lxml:data/lxml:fields/lxml:field[@name='AKTEST2']/lxml:value = 'J'">
 <xsl:attribute name="checked" />
</xsl:if>

<xsl:choose>
  <xsl:when test="expression">
    ... some output ...
  </xsl:when>
  <xsl:otherwise>
    ... some output ....
  </xsl:otherwise>
</xsl:choose>

XLST sum

Being hired to work on an extensive, complex and most of all, very used system, I naturally have to jump between different sides of the system. Having added some features to an application I then got back to XSLT.

One of the things I had to do was to generate a sum. Now, I could have done this in Lansa, but it was more logically done in XSLT so I did that. Except, since I could not remember the exact syntax I did a search and found many convoluted examples. And it is actually quite easy:

<xsl:value-of select="sum(XPATH)" />

Specifically I used it in this context:

<xsl:template match="/lxml:data/lxml:lists/lxml:list[@name='ESTLIST']">
<xsl:variable name="thelist"
 select="/lxml:data/lxml:lists/lxml:list[@name='ESTLIST']" />
...
<xsl:for-each select="$thelist/lxml:list-entries/lxml:entry">
 <xsl:variable name="BUTNR" select="lxml:column[@name='X_BUTNR']" />
 <xsl:variable name="BUKORT" select="lxml:column[@name='X_BUKORT']" />
 <xsl:variable name="EANTAL" select="lxml:column[@name='X_EANTAL']" /
...
</xsl:for-each>
...
<xsl:value-of select="sum($thelist/lxml:list-entries/lxml:entry/lxml:column[@name='X_EANTAL'])" />
...
</xsl:template>

The XML source was essentially

<?xml version="1.0"?>
 <lxml:data xmlns:lxml="http://www.lansa.com/2002/XML/Runtime-Data">
 <lxml:lists>
 <lxml:list name="ESTLIST" row-count="3">
 <lxml:list-header>
 <lxml:header name="X_BUTNR">...</lxml:header>
 <lxml:header name="X_BUKORT">...</lxml:header>
 <lxml:header name="X_EANTAL">...</lxml:header>
 </lxml:list-header>
 <lxml:list-entries>
 <lxml:entry>
 <lxml:column name="X_BUTNR" id="ESTLIST.0001.X_BUTNR">ABCD</lxml:column>
 <lxml:column name="X_BUKORT" id="ESTLIST.0001.X_BUKORT">aAbBcCdDeEfFgGh</lxml:column>
 <lxml:column name="X_EANTAL" id="ESTLIST.0001.X_EANTAL">12345</lxml:column>
 </lxml:entry>
 <lxml:entry>
 <lxml:column name="X_BUTNR" id="ESTLIST.0002.X_BUTNR">ABCD</lxml:column>
 <lxml:column name="X_BUKORT" id="ESTLIST.0002.X_BUKORT">aAbBcCdDeEfFgGh</lxml:column>
 <lxml:column name="X_EANTAL" id="ESTLIST.0002.X_EANTAL">12345</lxml:column>
 </lxml:entry>
 <lxml:entry>
 <lxml:column name="X_BUTNR" id="ESTLIST.0003.X_BUTNR">ABCD</lxml:column>
 <lxml:column name="X_BUKORT" id="ESTLIST.0003.X_BUKORT">aAbBcCdDeEfFgGh</lxml:column>
 <lxml:column name="X_EANTAL" id="ESTLIST.0003.X_EANTAL">12345</lxml:column>
 </lxml:entry>
 </lxml:list-entries>
 </lxml:list>
 </lxml:lists>
 </lxml:data>

XSLT

Working with Lansa, I also have to maintain some WAMs. This entails quite a bit of XSLT, so today I needed to produce a formatted number, except when the value was zero.

I ended up with this, which is supported by the XSLT parser:

<xsl:transform>
 ...
 <!-- decimal-format 'cause I am danish -->
 <xsl:decimal-format name="euro" decimal-separator="," grouping-separator="."
 NaN="" />
 ...
 <!-- sample call -->
 <xsl:call-template name="shoe_number2">
 <xsl:with-param name="numericvalue" select="$WPARDAG" />
 </xsl:call-template>
 ...
 <!-- templates -->
 <xsl:template name="shoe_number0">
 <xsl:param name="numericvalue" />
 <xsl:choose>
 <xsl:when test="$numericvalue = 0">
 </xsl:when>
 <xsl:otherwise>
 <xsl:value-of select="format-number(number(translate($numericvalue, ',', '.')), '###.###', 'euro')" />
 </xsl:otherwise>
 </xsl:choose>
 </xsl:template>
 <xsl:template name="shoe_number2">
 <xsl:param name="numericvalue" />
 <xsl:choose>
 <xsl:when test="$numericvalue = 0">
 </xsl:when>
 <xsl:otherwise>
 <xsl:value-of select="format-number(number(translate($numericvalue, ',', '.')), '###.###,00', 'euro')" />
 </xsl:otherwise>
 </xsl:choose>
 </xsl:template>
 <xsl:template name="shoe_index1">
 <xsl:param name="numericvalue" />
 <xsl:choose>
 <xsl:when test="$numericvalue = 0">
 </xsl:when>
 <xsl:otherwise>
 <xsl:value-of select="format-number(number(translate($numericvalue, ',', '.')), '#,0', 'euro')" />
 </xsl:otherwise>
 </xsl:choose>
 </xsl:template>
 <xsl:template name="shoe_index0">
 <xsl:param name="numericvalue" />
 <xsl:choose>
 <xsl:when test="$numericvalue = 0">
 </xsl:when>
 <xsl:otherwise>
 <xsl:value-of select="format-number(number(translate($numericvalue, ',', '.')), '#', 'euro')" />
 </xsl:otherwise>
 </xsl:choose>
 </xsl:template>
</xsl:transform>

Worked surprisingly well…