Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem with xsl:choose #92

Open
JohnGlauert opened this issue Apr 22, 2024 · 3 comments
Open

Problem with xsl:choose #92

JohnGlauert opened this issue Apr 22, 2024 · 3 comments
Assignees
Labels
bug Something isn't working

Comments

@JohnGlauert
Copy link

JohnGlauert commented Apr 22, 2024

I have a case where xsl:choose gives unexpected results but an equivalent pair of xsl:if elements works (using a browser solution with XSLTProcessor).

NOTE: I have corrected the text here. See later comment.

A cut down stylesheet working on:

<sign gloss="simple">
  <hamnosys_sign>
    <sign2>
      <minitialconfig2>
        <handconfig2>
          <handshape2>
            <handshape1 handshapeclass="ham_flathand"/>
          </handshape2>
        </handconfig2>
      </minitialconfig2>
    </sign2>
  </hamnosys_sign>
</sign>

should yield:

<hamgestural_sign>
  <sign_manual>
    <handconfig handshape="flat"/>
  </sign_manual>
</hamgestural_sign>

but yields:

<hamgestural_sign>
  <sign_manual>
    <handconfig>flat
    </handconfig>
  </sign_manual>
</hamgestural_sign>

Here is the (failing) stylesheet - cut back a lot:

<xsl:transform version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<!-- THESE OUTPUT SETTINGS MAY BE OVERRIDDEN BY THE H2S PROCESSOR: -->

<xsl:output method="xml" omit-xml-declaration="yes"
    indent="yes" encoding="UTF-8"/>

<!--######## handShapeValue ########-->

<xsl:template name="handShapeValue">

    <xsl:variable name="hs" select="@handshapeclass"/>

<!-- OK
    <xsl:value-of select="substring-after(concat(substring-before($hs,'hand'),$hs[not(contains(.,'hand'))]),'ham_')"/>
-->

<!-- OK
    <xsl:if test="$hs='ham_flathand'">
        <xsl:value-of select="'flat'"/>
    </xsl:if>
    <xsl:if test="$hs!='ham_flathand'">
        <xsl:value-of select="substring-after($hs,'ham_')"/>
    </xsl:if>
-->
<!-- Fails -->
    <xsl:choose>
        <xsl:when test="$hs='ham_flathand'">
            <xsl:value-of select="'flat'"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="substring-after($hs,'ham_')"/>
        </xsl:otherwise>
    </xsl:choose>

<!-- Fails
    <xsl:choose>
        <xsl:when test="$hs='ham_flathand'">
            <xsl:value-of select="'flat'"/>
        </xsl:when>
    </xsl:choose>
 -->
 
</xsl:template>

<!--######## sign ########-->

<xsl:template match="/">
    <!--
    <!ELEMENT sign (hamnosys_sign?)>
    <!ATTLIST sign gloss CDATA #IMPLIED>
    -->

    <xsl:element name="hamgestural_sign">

        <xsl:if test="@gloss">
            <xsl:attribute name="gloss">
                <xsl:value-of select="@gloss"/>
            </xsl:attribute>
        </xsl:if>

        <xsl:element name="sign_manual">
            <xsl:apply-templates select="sign/hamnosys_sign/sign2/minitialconfig2/handconfig2/handshape2/handshape1"/>
        </xsl:element>

    </xsl:element>

</xsl:template>

<!--######## handshape1 ########-->

<xsl:template match="handshape1">
    <!--
    <!ELEMENT handshape1 (
        fingernothumb*, fingershape*, fingercrossing*, thumbspecial?
    )>
    <!ATTLIST handshape1
        handshapeclass (%handshapeclass;) #REQUIRED
        fingerbending (%fingerbending;) #IMPLIED
        thumbpos (%thumbpos;) #IMPLIED
        second_handshapeclass (%handshapeclass;) #IMPLIED
        second_fingerbending (%fingerbending;) #IMPLIED
        second_thumbpos (%thumbpos;) #IMPLIED
        approx_shape %boolfalse;
    >
    -->

    <xsl:element name="handconfig">

        <xsl:variable name="hs">
            <xsl:call-template name="handShapeValue"/>
        </xsl:variable>

        <!-- handshape ATTRIBUTE -->
        <xsl:attribute name="handshape">
            <xsl:value-of select="$hs"/>
        </xsl:attribute>

    </xsl:element>

</xsl:template>

</xsl:transform>

There are several alternatives in template 'handShapeValue': One using a complex XPath expression - works; one using xsl:if - works; some using xsl:choose - don't work.

Looking at the high level code, xsl:if looks simpler and straightforward, while xsl:choose seems to use a different evaluation context, which maybe does not work in my case.

There may be other cases where xslt-processor is not working with my stylesheet as some output is duplicated. However, this seems to be a simple case where I am doing something wrong or there is an issue. I could convert all xsl:choose cases to xsl:if (even using XSLT!) but would rather not. The underlying stylesheet is very old and has been used without problems for many years - but it is several thousand lines long.

@leonelsanchesdasilva leonelsanchesdasilva self-assigned this Apr 23, 2024
@leonelsanchesdasilva
Copy link
Collaborator

@JohnGlauert Thanks for reporting. Convoluted cases is exactly what we need to make this library better.

@JohnGlauert
Copy link
Author

JohnGlauert commented Apr 24, 2024

AArrgghh!

I have sent you the wrong starting point for the stylesheet so the results will not make sense. In the actual process we use, the input:

<hns_sign gloss="simple">
  <hamnosys_manual>
    <hamflathand/>
  </hamnosys_manual>
</hns_sign>

is transformed by an earlier stage to:

<sign gloss="simple">
  <hamnosys_sign>
    <sign2>
      <minitialconfig2>
        <handconfig2>
          <handshape2>
            <handshape1 handshapeclass="ham_flathand"/>
          </handshape2>
        </handconfig2>
      </minitialconfig2>
    </sign2>
  </hamnosys_sign>
</sign>

This is then handled by the stylesheet as mentioned.

I have updated the original submission.

Apologies.

@leonelsanchesdasilva leonelsanchesdasilva added the bug Something isn't working label Sep 9, 2024
leonelsanchesdasilva added a commit that referenced this issue Sep 10, 2024
@leonelsanchesdasilva
Copy link
Collaborator

@JohnGlauert I added a unit test with this issue base inputs, but my results were different. I also ran a test at https://www.freeformatter.com/xsl-transformer.html, and the results were identical.

Input:

<sign gloss="simple">
    <hamnosys_sign>
        <sign2>
            <minitialconfig2>
                <handconfig2>
                    <handshape2>
                        <handshape1 handshapeclass="ham_flathand"/>
                    </handshape2>
                </handconfig2>
            </minitialconfig2>
        </sign2>
    </hamnosys_sign>
</sign>

XSLT:

<xsl:transform version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <!-- THESE OUTPUT SETTINGS MAY BE OVERRIDDEN BY THE H2S PROCESSOR: -->

    <xsl:output method="xml" omit-xml-declaration="yes"
        indent="yes" encoding="UTF-8"/>

    <!--######## handShapeValue ########-->

    <xsl:template name="handShapeValue">

        <xsl:variable name="hs" select="@handshapeclass"/>
        <xsl:value-of select="substring-after(concat(substring-before($hs,'hand'),$hs[not(contains(.,'hand'))]),'ham_')"/>

        <xsl:if test="$hs='ham_flathand'">
            <xsl:value-of select="'flat'"/>
        </xsl:if>
        <xsl:if test="$hs!='ham_flathand'">
            <xsl:value-of select="substring-after($hs,'ham_')"/>
        </xsl:if>

        <xsl:choose>
            <xsl:when test="$hs='ham_flathand'">
                <xsl:value-of select="'flat'"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="substring-after($hs,'ham_')"/>
            </xsl:otherwise>
        </xsl:choose>

        <xsl:choose>
            <xsl:when test="$hs='ham_flathand'">
                <xsl:value-of select="'flat'"/>
            </xsl:when>
        </xsl:choose>

    </xsl:template>

    <!--######## sign ########-->

    <xsl:template match="/">
        <!--
        <!ELEMENT sign (hamnosys_sign?)>
        <!ATTLIST sign gloss CDATA #IMPLIED>
        -->

        <xsl:element name="hamgestural_sign">

            <xsl:if test="@gloss">
                <xsl:attribute name="gloss">
                    <xsl:value-of select="@gloss"/>
                </xsl:attribute>
            </xsl:if>

            <xsl:element name="sign_manual">
                <xsl:apply-templates select="sign/hamnosys_sign/sign2/minitialconfig2/handconfig2/handshape2/handshape1"/>
            </xsl:element>

        </xsl:element>
    </xsl:template>
</xsl:transform>

Result:

<hamgestural_sign>
   <sign_manual/>
</hamgestural_sign>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants