p2p.wrox.com Forums

p2p.wrox.com Forums (http://p2p.wrox.com/index.php)
-   XSLT (http://p2p.wrox.com/forumdisplay.php?f=86)
-   -   preceding-sibling descendant (http://p2p.wrox.com/showthread.php?t=39113)

xaun February 27th, 2006 05:17 PM

preceding-sibling descendant
 
I am trying to put a list of class names in a table sometimes there needs to be 3 columns but most of the time there needs to be 4. If the Arg element in the XML is empty then there needs to be a </td></tr><tr> to close the sell and row and start another row. The below XSLT is not giving the desired result. This particular example is should be in 3 columns but the same XLST needs to be applicable for 3 and 4 columns.

Thanks in advance.

<xsl:template match="Group" >
    <table width="525">
        <tr>
            <td width="540" colspan="6"><xsl:value-of select="Header"/></td>
        </tr>
        <xsl:text disable-output-escaping="yes">
                &lt;tr&gt;
        </xsl:text>

        <xsl:for-each select="List/Course">

            <xsl:text disable-output-escaping="yes">
                &lt;td width="75" &gt;
            </xsl:text>
            <a href="javascript:poptastic('/myDegreePlanner/WebContent/jsps/coursedescription.jsp?course={Name}');"><xsl:value-of select="concat(Name,' ')"/> </a>
            <xsl:text disable-output-escaping="yes">
                &lt;/td&gt;
                &lt;td width="50" align="left" &gt;
            </xsl:text>
            <xsl:choose>
                <xsl:when test="Status = '(X)'">
                    <input name="" type="checkbox" disabled="true" value="" checked="checked" ></input>
                </xsl:when>
                <xsl:otherwise>
                    <input name="" type="checkbox" value="" />
                </xsl:otherwise>
            </xsl:choose>
            <xsl:value-of select="concat(Arg,' ')"/>
            <xsl:text disable-output-escaping="yes">
                    &lt;/td&gt;

            </xsl:text>

            <xsl:choose>
                <xsl:when test="Arg=''" >
                    <xsl:text disable-output-escaping="yes">
                        &lt;/tr&gt;&lt;tr&gt;

                    </xsl:text>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:choose>
                    <xsl:when test="position() mod 4 = 0" >
                        <xsl:if test="preceding-sibling::*[1][descendant::Arg] !=''">
                            <xsl:text disable-output-escaping="yes">
                                    &lt;/tr&gt;&lt;tr&gt;
                            </xsl:text>
                        </xsl:if>

                    </xsl:when>
                    <xsl:otherwise>
                            <xsl:if test="preceding-sibling::*[1][descendant::Arg] =''">

                            </xsl:if>

                    </xsl:otherwise>
                     </xsl:choose>
                </xsl:otherwise>
            </xsl:choose>

        </xsl:for-each>
        <xsl:text disable-output-escaping="yes">
            &lt;/tr&gt;
        </xsl:text>


    </table>
</xsl:template>

The XML looks like
<List>
                    <Course>
                        <Name>ORI2000</Name>
                        <Status>( )</Status>
                        <Arg>or</Arg>
                    </Course>
                    <Course>
                        <Name>SPC2016</Name>
                        <Status>( )</Status>
                        <Arg>or</Arg>
                    </Course>
                    <Course>
                        <Name>SPC2040</Name>
                        <Status>( )</Status>
                        <Arg/>
                    </Course>
                    <Course>
                        <Name>SPC2600</Name>
                        <Status>( )</Status>
                        <Arg>or</Arg>
                    </Course>
                    <Course>
                        <Name>MAC1102</Name>
                        <Status>( )</Status>
                        <Arg>or</Arg>
                    </Course>
                    <Course>
                        <Name>MAC1105</Name>
                        <Status>( )</Status>
                        <Arg/>
                    </Course>
                    <Course>
                        <Name>MAC1140</Name>
                        <Status>( )</Status>
                        <Arg>or</Arg>
                    </Course>
                    <Course>
                        <Name>MAC1114</Name>
                        <Status>( )</Status>
                        <Arg>or</Arg>
                    </Course>
                    <Course>
                        <Name>MAC1147</Name>
                        <Status>( )</Status>
                        <Arg/>
                    </Course>
                    <Course>
                        <Name>MAC2233</Name>
                        <Status>( )</Status>
                        <Arg>or</Arg>
                    </Course>
The results look like
ORI2000 or SPC2016 or SPC2040
SPC2600 or
MAC1102 or MAC1105
MAC1140 or MAC1114 or
MAC1147


mhkay February 27th, 2006 07:07 PM

This is not the way to write XSLT:

       <xsl:text disable-output-escaping="yes">
                &lt;tr&gt;
        </xsl:text>

XSLT is a language for transforming input trees into result trees. The result tree is then (optionally) sent to a serializer to be turned into serial XML. Very occasionally you need to prod the serializer to do something unusual, and that is the only time you should use disable-output-escaping. What you are trying to do here is to bend XSLT into a language for writing textual XML, in the form of tags, and you are getting yourself into a mess as a result.

Writing a node to a tree is an atomic action, achieved using a literal result element if it's name is known statically, or xsl:element if not. You don't write one half of the node at one time, and the other half later.

To write a table with data items arranged four per row, your logic should look like this:

<table>
 for each group of four items
  <tr>
    for each of the four items
      <td>
        output the item

for example

<table>
 <xsl:for-each select="Course[position() mod 4 = 1]">
  <tr>
   <xsl:for-each select=".|following-sibling::Course[position() &lt; 4]">
     <td>
       <xsl:apply-templates/>
     </td>
   </xsl:for-each>
  </tr>
 </xsl:for-each>
</table>

Sorry not to help you with your immediate problem, but this code is no place to start from.




Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference

xaun February 28th, 2006 10:29 AM

Thank you for your comment however this is only an example of my problem. The problem that I am trying to solve goes much deeper and I did not wish to go into the details on this list and thus far the only way that I can see to address it is to use the stratagy that I have employed. I welcome any comments that will help me address the issue of sibling descendancency.

Thank you




xaun February 28th, 2006 02:48 PM

For anyone who is interested the solution to my problem is as follows.

<xsl:choose>
                <xsl:when test="position() mod 4 = 0" >
                    <xsl:if test="(preceding-sibling::*[1]/Arg !='' and following-sibling::*[1]/Arg !='') or position()=last()">
                        <xsl:text disable-output-escaping="yes">
                            &lt;/tr&gt;&lt;tr&gt;
                        </xsl:text>
                    </xsl:if>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:if test="Arg =''" >
                        <xsl:text disable-output-escaping="yes">
                            &lt;/tr&gt;&lt;tr&gt;
                        </xsl:text>
                    </xsl:if>
                </xsl:otherwise>

            </xsl:choose>
            <xsl:choose>
                <xsl:when test="position() mod 4 = 0" >
                    <xsl:if test="position()+1=last()" >
                        <xsl:text disable-output-escaping="yes">
                            &lt;/tr&gt;&lt;tr&gt;
                        </xsl:text>
                    </xsl:if>
                </xsl:when>
            </xsl:choose>




All times are GMT -4. The time now is 03:52 PM.

Powered by vBulletin®
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
© 2013 John Wiley & Sons, Inc.