Suspected XSLT issue; Failing "choose"
Added by Anonymous about 19 years ago
Legacy ID: #3314085 Legacy Poster: Lars J. Nilsson (larsan)
Hello, Following this text I will include two test documents "test.xml" and "test.xsl" which are snipplets from my live code demonstrating a failing "choose" contruct in a stylesheet. This particular bit of code have failed in both Saxon 6.5.4 and Saxon-B 8.5.1. The files in this post have been tested on Saxon-B 8.5.1 using a vanilla Java JDK install... >>> java version "1.4.2_08" Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_08-b03) Java HotSpot(TM) Client VM (build 1.4.2_08-b03, mixed mode) >>> .. and the following command line: >>> java -classpath saxonb-8.5.1.jar net.sf.saxon.Transform -v -o test.html test.xml test.xsl 2> err.txt >>> The problem is the "para"-matching template at line 15 when called from a nested context (line 51). It does a truly trivial match (on "true()") and encloses anything in HTML divs according to the test. Looking at the source document the first "para" (at line 5) is transformed correctly. However, the following "para" elements enclosed within "description" elements are not correctly transformed, they get enclosing "div" in the output. The template explicitly handles the "form" element decendants down to the "description" element and then calls "apply-templates" (at line 51 in the stylesheet). Removing the "choose"-contruct in the "para"-template and eclosing everything in the same "div" element does work. Regards - Lars J. Nillsson test.xml >>> <template xml:space="default"> <page> <content> <section title="Signup"> <para>A simple confimration para.</para> <form action="./" method="post" name="signupform"> <field name="is-submission" type="hidden" value="true" label="is-submission"/> <field name="username" id="username" type="text" label="Username"/> <field name="password" id="password" type="password" label="Password"> <description> <para>Small first para.</para> </description> </field> <field name="password_c" id="password_c" type="password" label="Confirm password"/> <field name="email" id="email" type="text" label="Email"> <description> <para>Small second para.</para> </description> </field> <field name="captcha" id="captcha" type="text" label="Confirm"> <description> <para>This is the captcha text.</para> </description> </field> </form> </section> </content> </page> </template> >>> test.xml test.xsl >>> <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN" doctype-system="http://www.w3.org/TR/html4/loose.dtd" /> <!-- - Error: This template does not work when called from line 51 as a child - element of "description" --> <xsl:template match="para" > <xsl:choose> <xsl:when test="true()"> <div class="correct-para"><xsl:apply-templates /></div> </xsl:when> <xsl:otherwise> <div class="incorrect-para"><xsl:apply-templates /></div> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="form" > <form action="{@action}" method="{@method}"> <xsl:if test="@style"> <xsl:attribute name="style"><xsl:value-of select="@style" /></xsl:attribute> </xsl:if> <xsl:if test="@class"> <xsl:attribute name="class"><xsl:value-of select="@class" /></xsl:attribute> </xsl:if> <xsl:for-each select="field[@type = 'hidden']"> <input type="hidden" value="{@value}" name="{@name}" /> </xsl:for-each> <table cellpadding="0" cellspacing="0" border="0" class="formtable"> <tbody> <xsl:apply-templates /> </tbody> </table> </form> </xsl:template> <xsl:template match="field[@type != 'hidden']"> <xsl:if test="description"> <tr> <td class="formcell"></td> <td class="formcell"> <xsl:for-each select="description/"> <xsl:apply-templates /> </xsl:for-each> </td> </tr> </xsl:if> <tr> <td class="formcell" valign="top"> <xsl:if test="@label and @type != 'submit' and @type != 'checkbox'"> <div class="formlabel"> <xsl:value-of select="@label" /><xsl:text>: </xsl:text> </div> </xsl:if> </td> <td class="formcell" width="75%"> <xsl:call-template name="put-field" /> <xsl:if test="@type = 'checkbox'"> <span class="checkboxlabel"> <xsl:value-of select="@label" /> </span> </xsl:if> </td> </tr> <xsl:if test="error"> <tr> <td class="formcell"></td> <td class="formcell"> <div class="formerror"> <xsl:text> </xsl:text><xsl:value-of select="error/text()" /> </div> </td> </tr> </xsl:if> </xsl:template> <xsl:template name="put-field" > <xsl:choose> <xsl:when test="@type = 'option'"> <select name="{@name}"> <xsl:if test="@style"> <xsl:attribute name="style"><xsl:value-of select="@style" /></xsl:attribute> </xsl:if> <xsl:if test="@class"> <xsl:attribute name="class"><xsl:value-of select="@class" /></xsl:attribute> </xsl:if> <xsl:if test="@id"> <xsl:attribute name="id"><xsl:value-of select="@id" /></xsl:attribute> </xsl:if> <option value="">Please select: </option> <xsl:for-each select="option"> <xsl:element name="option"> <xsl:attribute name="value"><xsl:value-of select="@value" /></xsl:attribute> <xsl:if test="@selected = 'true'"> <xsl:attribute name="selected"><xsl:value-of select="'selected'" /></xsl:attribute> </xsl:if> <xsl:value-of select="@name" /> </xsl:element> </xsl:for-each> </select> </xsl:when> <xsl:when test="@type = 'textarea'"> <textarea name="{@name}" cols="50" rows="20"> <xsl:if test="@style"> <xsl:attribute name="style"><xsl:value-of select="@style" /></xsl:attribute> </xsl:if> <xsl:if test="@class"> <xsl:attribute name="class"><xsl:value-of select="@class" /></xsl:attribute> </xsl:if> <xsl:if test="@id"> <xsl:attribute name="id"><xsl:value-of select="@id" /></xsl:attribute> </xsl:if> <xsl:value-of select="@value" /> </textarea> </xsl:when> <xsl:when test="@type != 'submit'"> <input type="{@type}" value="{@value}" name="{@name}"> <xsl:if test="@type = 'checkbox' and @value = 'true'"> <xsl:attribute name="checked"><xsl:value-of select="'checked'" /></xsl:attribute> </xsl:if> <xsl:if test="@style"> <xsl:attribute name="style"><xsl:value-of select="@style" /></xsl:attribute> </xsl:if> <xsl:if test="@class"> <xsl:attribute name="class"><xsl:value-of select="@class" /></xsl:attribute> </xsl:if> <xsl:if test="@image"> <xsl:attribute name="src"><xsl:value-of select="@image" /></xsl:attribute> </xsl:if> <xsl:if test="@id"> <xsl:attribute name="id"><xsl:value-of select="@id" /></xsl:attribute> </xsl:if> </input> </xsl:when> <xsl:otherwise> <button type="submit" value="{@value}"> <xsl:if test="@style"> <xsl:attribute name="style"><xsl:value-of select="@style" /></xsl:attribute> </xsl:if> <xsl:if test="@class"> <xsl:attribute name="class"><xsl:value-of select="@class" /></xsl:attribute> </xsl:if> <xsl:if test="@image"> <xsl:attribute name="src"><xsl:value-of select="@image" /></xsl:attribute> </xsl:if> <xsl:if test="@id"> <xsl:attribute name="id"><xsl:value-of select="@id" /></xsl:attribute> </xsl:if> <xsl:value-of select="@label" /> </button> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet> >>> test.xsl
Replies (2)
RE: Suspected XSLT issue; Failing "choose" - Added by Anonymous about 19 years ago
Legacy ID: #3314184 Legacy Poster: Michael Kay (mhkay)
Remember that <xsl:apply-templates/> with no select attribute means <xsl:apply-templates select="child::node()"/>. So when you write: <xsl:for-each select="description/"> <xsl:apply-templates /> </xsl:for-each> you are processing the child elements of description (the para element) and then applying templates to the children of the para element (the text node): the built-in template rule for text nodes simply copies the text to the result tree. I suspect the above code should simply be replaced by <xsl:apply-templates select="description/"/> I can't see how you came to the conclusion that the xsl:choose is relevant. Replacing the "para" template by <xsl:template match="para" > <div class="correct-para"><xsl:apply-templates /></div> </xsl:template> produces exactly the same output, as you would expect. Michael Kay http://www.saxonica.com/ P.S. Try the -T option on the command line to trace the execution of template rules, it can greatly help with debugging this kind of problem.
RE: Suspected XSLT issue; Failing "choose" - Added by Anonymous about 19 years ago
Legacy ID: #3314769 Legacy Poster: Lars J. Nilsson (larsan)
Ooouch! There's me spraying my morning coffe all over the keyboard again. I can't believe I just screwed up that badly. [insert long rant with a lot of swedish swearwords here] Of course it does. You have my heartfelt appologies for bothering you. And my thanks for pointing out the fairly obvious error, I would most likely have spent quite a few hours just staring at it otherwise. And while I'm at it, thanks for a good product. I switched to saxon when xalan and/or the resin libs repeatedly failed to produce what I thought was fairly trivial. And I'll check out the -T flag, all of my XML and some of my XSL is dynamically produced in SAX-based pipelines so I normally don't use the command line at all. Obviously, after this... emberrasment, I probably will. Yes... I think I shall.
Please register to reply