Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 327
  • Last Modified:

hierarchy rendering in XML using XSLT

Hi

I have the following XML file (over which I have no control).  A snippet is attached - there are a lot more rows with different data here.

<ROWSET>
<ROW>
    <ROWNUM>80</ROWNUM>
    <PROPOSAL_TYPE>TEST</PROPOSAL_TYPE>
    <TREE_LEVEL>1</TREE_LEVEL>
    <PATH>/MAJOR</PATH>
    <PROPOSAL_ELEMENT_CD>MAJOR</PROPOSAL_ELEMENT_CD>
    <S_ELEMENT_CD>USERDEF</S_ELEMENT_CD>
    <SUP_PROPOSAL_ELEMENT_CD/>
    <ELEMENT_HEADING>MAJOR/SPECIALISATION</ELEMENT_HEADING>
    <ELEMENT_DISPLAY_ORDER>12</ELEMENT_DISPLAY_ORDER>
    <ELEMENT_MULTIPLE_INST_IND>N</ELEMENT_MULTIPLE_INST_IND>
    <ELEMENT_CONTENT_ITERATION>1</ELEMENT_CONTENT_ITERATION>
    <PIE_SEQUENCE_NUMBER>1465</PIE_SEQUENCE_NUMBER>
    <SUP_PIE_SEQUENCE_NUMBER/>
    <PROPOSAL_ITEM_CD>MAJNOTES</PROPOSAL_ITEM_CD>
    <S_PROPOSAL_ITEM_CD>CHAR</S_PROPOSAL_ITEM_CD>
    <S_INPUT_FIELD_TYPE>TEXTFIELD</S_INPUT_FIELD_TYPE>
    <S_FIELD_TYPE>VARCHAR</S_FIELD_TYPE>
    <RICH_TEXT_IND>N</RICH_TEXT_IND>
    <PROMPT>Comments/Notes</PROMPT>
    <FIELD_LENGTH>4000</FIELD_LENGTH>
    <ITEM_DISPLAY_ORDER>4</ITEM_DISPLAY_ORDER>
    <CHAR_VALUE>*The first major must be taken from the majors available at Caulfield campus.
**Electives may be chosen to complete a second major.
***Depending on the major chosen, one or more of the units in the major may have already been studied as part of the group of level one common core units in which case a student will complete an additional elective unit.
</CHAR_VALUE>
    <NUMBER_VALUE/>
    <DATE_VALUE/>
    <CLOB_VALUE/>
    <INSERT_IND>Y</INSERT_IND>
    <DELETE_IND>N</DELETE_IND>
    <UPDATE_IND>N</UPDATE_IND>
    <DISPLAY_IN_MENU_IND>N</DISPLAY_IN_MENU_IND>
  </ROW>
  <ROW>
    <ROWNUM>81</ROWNUM>
    <PROPOSAL_TYPE>TEST</PROPOSAL_TYPE>
    <TREE_LEVEL>2</TREE_LEVEL>
    <PATH>/MAJOR/MAJTLS</PATH>
    <PROPOSAL_ELEMENT_CD>MAJTLS</PROPOSAL_ELEMENT_CD>
    <S_ELEMENT_CD>USERDEF</S_ELEMENT_CD>
    <SUP_PROPOSAL_ELEMENT_CD>MAJOR</SUP_PROPOSAL_ELEMENT_CD>
    <ELEMENT_HEADING>MAJOR/SPECIALISATION TITLES</ELEMENT_HEADING>
    <ELEMENT_DISPLAY_ORDER>13</ELEMENT_DISPLAY_ORDER>
    <ELEMENT_MULTIPLE_INST_IND>Y</ELEMENT_MULTIPLE_INST_IND>
    <ELEMENT_CONTENT_ITERATION>1</ELEMENT_CONTENT_ITERATION>
    <PIE_SEQUENCE_NUMBER>1466</PIE_SEQUENCE_NUMBER>
    <SUP_PIE_SEQUENCE_NUMBER>1465</SUP_PIE_SEQUENCE_NUMBER>
    <PROPOSAL_ITEM_CD>MAJTL</PROPOSAL_ITEM_CD>
    <S_PROPOSAL_ITEM_CD>CHAR</S_PROPOSAL_ITEM_CD>
    <S_INPUT_FIELD_TYPE>TEXTFIELD</S_INPUT_FIELD_TYPE>
    <S_FIELD_TYPE>VARCHAR</S_FIELD_TYPE>
    <RICH_TEXT_IND>N</RICH_TEXT_IND>
    <PROMPT>Major/Specialisation Title</PROMPT>
    <FIELD_LENGTH>255</FIELD_LENGTH>
    <ITEM_DISPLAY_ORDER>1</ITEM_DISPLAY_ORDER>
    <CHAR_VALUE>Major Title 1</CHAR_VALUE>
    <NUMBER_VALUE/>
    <DATE_VALUE/>
    <CLOB_VALUE/>
    <INSERT_IND>Y</INSERT_IND>
    <DELETE_IND>N</DELETE_IND>
    <UPDATE_IND>N</UPDATE_IND>
    <DISPLAY_IN_MENU_IND>Y</DISPLAY_IN_MENU_IND>
  </ROW>
  <ROW>
    <ROWNUM>82</ROWNUM>
    <PROPOSAL_TYPE>TEST</PROPOSAL_TYPE>
    <TREE_LEVEL>2</TREE_LEVEL>
    <PATH>/MAJOR/MAJTLS</PATH>
    <PROPOSAL_ELEMENT_CD>MAJTLS</PROPOSAL_ELEMENT_CD>
    <S_ELEMENT_CD>USERDEF</S_ELEMENT_CD>
    <SUP_PROPOSAL_ELEMENT_CD>MAJOR</SUP_PROPOSAL_ELEMENT_CD>
    <ELEMENT_HEADING>MAJOR/SPECIALISATION TITLES</ELEMENT_HEADING>
    <ELEMENT_DISPLAY_ORDER>13</ELEMENT_DISPLAY_ORDER>
    <ELEMENT_MULTIPLE_INST_IND>Y</ELEMENT_MULTIPLE_INST_IND>
    <ELEMENT_CONTENT_ITERATION>2</ELEMENT_CONTENT_ITERATION>
    <PIE_SEQUENCE_NUMBER>1467</PIE_SEQUENCE_NUMBER>
    <SUP_PIE_SEQUENCE_NUMBER>1465</SUP_PIE_SEQUENCE_NUMBER>
    <PROPOSAL_ITEM_CD>MAJTL</PROPOSAL_ITEM_CD>
    <S_PROPOSAL_ITEM_CD>CHAR</S_PROPOSAL_ITEM_CD>
    <S_INPUT_FIELD_TYPE>TEXTFIELD</S_INPUT_FIELD_TYPE>
    <S_FIELD_TYPE>VARCHAR</S_FIELD_TYPE>
    <RICH_TEXT_IND>N</RICH_TEXT_IND>
    <PROMPT>Major/Specialisation Title</PROMPT>
    <FIELD_LENGTH>255</FIELD_LENGTH>
    <ITEM_DISPLAY_ORDER>1</ITEM_DISPLAY_ORDER>
    <CHAR_VALUE>Major Title 2</CHAR_VALUE>
    <NUMBER_VALUE/>
    <DATE_VALUE/>
    <CLOB_VALUE/>
    <INSERT_IND>Y</INSERT_IND>
    <DELETE_IND>N</DELETE_IND>
    <UPDATE_IND>N</UPDATE_IND>
    <DISPLAY_IN_MENU_IND>Y</DISPLAY_IN_MENU_IND>
  </ROW>
  <ROW>
    <ROWNUM>83</ROWNUM>
    <PROPOSAL_TYPE>TEST</PROPOSAL_TYPE>
    <TREE_LEVEL>2</TREE_LEVEL>
    <PATH>/MAJOR/MAJTLS</PATH>
    <PROPOSAL_ELEMENT_CD>MAJTLS</PROPOSAL_ELEMENT_CD>
    <S_ELEMENT_CD>USERDEF</S_ELEMENT_CD>
    <SUP_PROPOSAL_ELEMENT_CD>MAJOR</SUP_PROPOSAL_ELEMENT_CD>
    <ELEMENT_HEADING>MAJOR/SPECIALISATION TITLES</ELEMENT_HEADING>
    <ELEMENT_DISPLAY_ORDER>13</ELEMENT_DISPLAY_ORDER>
    <ELEMENT_MULTIPLE_INST_IND>Y</ELEMENT_MULTIPLE_INST_IND>
    <ELEMENT_CONTENT_ITERATION>3</ELEMENT_CONTENT_ITERATION>
    <PIE_SEQUENCE_NUMBER>1468</PIE_SEQUENCE_NUMBER>
    <SUP_PIE_SEQUENCE_NUMBER>1465</SUP_PIE_SEQUENCE_NUMBER>
    <PROPOSAL_ITEM_CD>MAJTL</PROPOSAL_ITEM_CD>
    <S_PROPOSAL_ITEM_CD>CHAR</S_PROPOSAL_ITEM_CD>
    <S_INPUT_FIELD_TYPE>TEXTFIELD</S_INPUT_FIELD_TYPE>
    <S_FIELD_TYPE>VARCHAR</S_FIELD_TYPE>
    <RICH_TEXT_IND>N</RICH_TEXT_IND>
    <PROMPT>Major/Specialisation Title</PROMPT>
    <FIELD_LENGTH>255</FIELD_LENGTH>
    <ITEM_DISPLAY_ORDER>1</ITEM_DISPLAY_ORDER>
    <CHAR_VALUE>Major Title 3</CHAR_VALUE>
    <NUMBER_VALUE/>
    <DATE_VALUE/>
    <CLOB_VALUE/>
    <INSERT_IND>Y</INSERT_IND>
    <DELETE_IND>N</DELETE_IND>
    <UPDATE_IND>N</UPDATE_IND>
    <DISPLAY_IN_MENU_IND>Y</DISPLAY_IN_MENU_IND>
  </ROW>
  <ROW>
    <ROWNUM>84</ROWNUM>
    <PROPOSAL_TYPE>TEST</PROPOSAL_TYPE>
    <TREE_LEVEL>3</TREE_LEVEL>
    <PATH>/MAJOR/MAJTLS/MAJREQS</PATH>
    <PROPOSAL_ELEMENT_CD>MAJREQS</PROPOSAL_ELEMENT_CD>
    <S_ELEMENT_CD>USERDEF</S_ELEMENT_CD>
    <SUP_PROPOSAL_ELEMENT_CD>MAJTLS</SUP_PROPOSAL_ELEMENT_CD>
    <ELEMENT_HEADING>COURSE REQUIREMENTS</ELEMENT_HEADING>
    <ELEMENT_DISPLAY_ORDER>14</ELEMENT_DISPLAY_ORDER>
    <ELEMENT_MULTIPLE_INST_IND>Y</ELEMENT_MULTIPLE_INST_IND>
    <ELEMENT_CONTENT_ITERATION>1</ELEMENT_CONTENT_ITERATION>
    <PIE_SEQUENCE_NUMBER>1469</PIE_SEQUENCE_NUMBER>
    <SUP_PIE_SEQUENCE_NUMBER>1468</SUP_PIE_SEQUENCE_NUMBER>
    <PROPOSAL_ITEM_CD>MAJTL2</PROPOSAL_ITEM_CD>
    <S_PROPOSAL_ITEM_CD>CHAR</S_PROPOSAL_ITEM_CD>
    <S_INPUT_FIELD_TYPE>TEXTFIELD</S_INPUT_FIELD_TYPE>
    <S_FIELD_TYPE>VARCHAR</S_FIELD_TYPE>
    <RICH_TEXT_IND>N</RICH_TEXT_IND>
    <PROMPT>Major/Specialisation Title</PROMPT>
    <FIELD_LENGTH>255</FIELD_LENGTH>
    <ITEM_DISPLAY_ORDER>1</ITEM_DISPLAY_ORDER>
    <CHAR_VALUE/>
    <NUMBER_VALUE/>
    <DATE_VALUE/>
    <CLOB_VALUE/>
    <INSERT_IND>Y</INSERT_IND>
    <DELETE_IND>N</DELETE_IND>
    <UPDATE_IND>N</UPDATE_IND>
    <DISPLAY_IN_MENU_IND>Y</DISPLAY_IN_MENU_IND>
  </ROW>
  <ROW>
    <ROWNUM>85</ROWNUM>
    <PROPOSAL_TYPE>TEST</PROPOSAL_TYPE>
    <TREE_LEVEL>3</TREE_LEVEL>
    <PATH>/MAJOR/MAJTLS/MAJREQS</PATH>
    <PROPOSAL_ELEMENT_CD>MAJREQS</PROPOSAL_ELEMENT_CD>
    <S_ELEMENT_CD>USERDEF</S_ELEMENT_CD>
    <SUP_PROPOSAL_ELEMENT_CD>MAJTLS</SUP_PROPOSAL_ELEMENT_CD>
    <ELEMENT_HEADING>COURSE REQUIREMENTS</ELEMENT_HEADING>
    <ELEMENT_DISPLAY_ORDER>14</ELEMENT_DISPLAY_ORDER>
    <ELEMENT_MULTIPLE_INST_IND>Y</ELEMENT_MULTIPLE_INST_IND>
    <ELEMENT_CONTENT_ITERATION>1</ELEMENT_CONTENT_ITERATION>
    <PIE_SEQUENCE_NUMBER>1469</PIE_SEQUENCE_NUMBER>
    <SUP_PIE_SEQUENCE_NUMBER>1468</SUP_PIE_SEQUENCE_NUMBER>
    <PROPOSAL_ITEM_CD>MAUNCD</PROPOSAL_ITEM_CD>
    <S_PROPOSAL_ITEM_CD>CHAR</S_PROPOSAL_ITEM_CD>
    <S_INPUT_FIELD_TYPE>TEXTFIELD</S_INPUT_FIELD_TYPE>
    <S_FIELD_TYPE>VARCHAR</S_FIELD_TYPE>
    <RICH_TEXT_IND>N</RICH_TEXT_IND>
    <PROMPT>Unit Code</PROMPT>
    <FIELD_LENGTH>7</FIELD_LENGTH>
    <ITEM_DISPLAY_ORDER>2</ITEM_DISPLAY_ORDER>
    <CHAR_VALUE/>
    <NUMBER_VALUE/>
    <DATE_VALUE/>
    <CLOB_VALUE/>
    <INSERT_IND>Y</INSERT_IND>
    <DELETE_IND>N</DELETE_IND>
    <UPDATE_IND>N</UPDATE_IND>
    <DISPLAY_IN_MENU_IND>Y</DISPLAY_IN_MENU_IND>
  </ROW>
  <ROW>
    <ROWNUM>86</ROWNUM>
    <PROPOSAL_TYPE>TEST</PROPOSAL_TYPE>
    <TREE_LEVEL>3</TREE_LEVEL>
    <PATH>/MAJOR/MAJTLS/MAJREQS</PATH>
    <PROPOSAL_ELEMENT_CD>MAJREQS</PROPOSAL_ELEMENT_CD>
    <S_ELEMENT_CD>USERDEF</S_ELEMENT_CD>
    <SUP_PROPOSAL_ELEMENT_CD>MAJTLS</SUP_PROPOSAL_ELEMENT_CD>
    <ELEMENT_HEADING>COURSE REQUIREMENTS</ELEMENT_HEADING>
    <ELEMENT_DISPLAY_ORDER>14</ELEMENT_DISPLAY_ORDER>
    <ELEMENT_MULTIPLE_INST_IND>Y</ELEMENT_MULTIPLE_INST_IND>
    <ELEMENT_CONTENT_ITERATION>1</ELEMENT_CONTENT_ITERATION>
    <PIE_SEQUENCE_NUMBER>1469</PIE_SEQUENCE_NUMBER>
    <SUP_PIE_SEQUENCE_NUMBER>1468</SUP_PIE_SEQUENCE_NUMBER>
    <PROPOSAL_ITEM_CD>MAUNTL</PROPOSAL_ITEM_CD>
    <S_PROPOSAL_ITEM_CD>CHAR</S_PROPOSAL_ITEM_CD>
    <S_INPUT_FIELD_TYPE>TEXTFIELD</S_INPUT_FIELD_TYPE>
    <S_FIELD_TYPE>VARCHAR</S_FIELD_TYPE>
    <RICH_TEXT_IND>N</RICH_TEXT_IND>
    <PROMPT>Unit Title</PROMPT>
    <FIELD_LENGTH>100</FIELD_LENGTH>
    <ITEM_DISPLAY_ORDER>3</ITEM_DISPLAY_ORDER>
    <CHAR_VALUE/>
    <NUMBER_VALUE/>
    <DATE_VALUE/>
    <CLOB_VALUE/>
    <INSERT_IND>Y</INSERT_IND>
    <DELETE_IND>N</DELETE_IND>
    <UPDATE_IND>N</UPDATE_IND>
    <DISPLAY_IN_MENU_IND>Y</DISPLAY_IN_MENU_IND>
  </ROW>
  <ROW>
    <ROWNUM>87</ROWNUM>
    <PROPOSAL_TYPE>TEST</PROPOSAL_TYPE>
    <TREE_LEVEL>3</TREE_LEVEL>
    <PATH>/MAJOR/MAJTLS/MAJREQS</PATH>
    <PROPOSAL_ELEMENT_CD>MAJREQS</PROPOSAL_ELEMENT_CD>
    <S_ELEMENT_CD>USERDEF</S_ELEMENT_CD>
    <SUP_PROPOSAL_ELEMENT_CD>MAJTLS</SUP_PROPOSAL_ELEMENT_CD>
    <ELEMENT_HEADING>COURSE REQUIREMENTS</ELEMENT_HEADING>
    <ELEMENT_DISPLAY_ORDER>14</ELEMENT_DISPLAY_ORDER>
    <ELEMENT_MULTIPLE_INST_IND>Y</ELEMENT_MULTIPLE_INST_IND>
    <ELEMENT_CONTENT_ITERATION>1</ELEMENT_CONTENT_ITERATION>
    <PIE_SEQUENCE_NUMBER>1469</PIE_SEQUENCE_NUMBER>
    <SUP_PIE_SEQUENCE_NUMBER>1468</SUP_PIE_SEQUENCE_NUMBER>
    <PROPOSAL_ITEM_CD>MACRPT</PROPOSAL_ITEM_CD>
    <S_PROPOSAL_ITEM_CD>NUMBER</S_PROPOSAL_ITEM_CD>
    <S_INPUT_FIELD_TYPE>TEXTFIELD</S_INPUT_FIELD_TYPE>
    <S_FIELD_TYPE>NUMBER</S_FIELD_TYPE>
    <RICH_TEXT_IND>N</RICH_TEXT_IND>
    <PROMPT>Credit Points</PROMPT>
    <FIELD_LENGTH>10.1</FIELD_LENGTH>
    <ITEM_DISPLAY_ORDER>4</ITEM_DISPLAY_ORDER>
    <CHAR_VALUE/>
    <NUMBER_VALUE/>
    <DATE_VALUE/>
    <CLOB_VALUE/>
    <INSERT_IND>Y</INSERT_IND>
    <DELETE_IND>N</DELETE_IND>
    <UPDATE_IND>N</UPDATE_IND>
    <DISPLAY_IN_MENU_IND>Y</DISPLAY_IN_MENU_IND>
  </ROW>
...
</ROWSET>

Open in new window

 
The records above are an exerpt from a larger document, and relate to the major for a university course, ordered by the course detail, then the list of majors as a number of rows, then the attributes of each major, in a number of rows.

The hierachy between the records is set up in the PIE_SEQUENCE_NUMBER and the SUP_PIE_SEQUENCE_NUMBER fields of the ROW - the PIE_SEQUENCE_NUMBER of the parent is recorded in the SUP_PIE_SEQUENCE_NUMBER of the child.  

So, for anything with a <PATH> that includes MAJOR, I want to render these rows in their hierarchy, i.e. each child follows its parent row recursively.  The XSL I am working with has a template called multi_instance_table which is set up to render the rows in the XML into table format.  This seems to work fine.  However, currently, it renders each block of rows independently and does not account for the child relationship.  I believe that this is because where there is a child relationship, the template it does not recursively call itself to render the children in the context of the current ROW.

The template we have been supplied with looks like this (only part of the broader XSL):

<xsl:template name="multi_instance_table">
        <xsl:param name="rownum" select="ROWNUM"/>
        
        <xsl:variable name="isempty">
            <xsl:choose>
                <xsl:when test="//ROW[ROWNUM=($rownum)]/S_FIELD_TYPE='CLOB'">
                    <xsl:choose>
                        <xsl:when test="//ROW[ROWNUM=($rownum)]/CLOB_VALUE[not(text())]">
                            true
                        </xsl:when>
                        <xsl:otherwise>
                            false
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:when>
                <xsl:when test="//ROW[ROWNUM=($rownum)]/S_FIELD_TYPE='NUMBER'">
                    <xsl:choose>
                        <xsl:when test="//ROW[ROWNUM=($rownum)]/NUMBER_VALUE[not(text())]">
                            true
                        </xsl:when>
                        <xsl:otherwise>
                            false
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:when>
                <xsl:when test="//ROW[ROWNUM=($rownum)]/S_FIELD_TYPE='DATE'">
                    <xsl:choose>
                        <xsl:when test="//ROW[ROWNUM=($rownum)]/DATE_VALUE[not(text())]">
                            true
                        </xsl:when>
                        <xsl:otherwise>
                            false
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:choose>
                        <xsl:when test="//ROW[ROWNUM=($rownum)]/CHAR_VALUE[not(text())]">
                            true
                        </xsl:when>
                        <xsl:otherwise>
                            false
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        
        <xsl:if test="$rownum=1 or PROPOSAL_ELEMENT_CD != string(//ROW[($rownum)-1]/PROPOSAL_ELEMENT_CD)">
            <tr>
                <td align="left" colspan="100">
                    
                    <table spacing="0">
                        <tr>
                            <xsl:call-template name="do_padding">
                                <xsl:with-param name="pad_amount" select="TREE_LEVEL"/>
                            </xsl:call-template>
                            <xsl:call-template name="multi_instance_table_heading">
                                <xsl:with-param name="rownum" select="$rownum"/>
                            </xsl:call-template>
                        </tr>
                        <xsl:call-template name="multi_instance_table_row">
                            <xsl:with-param name="rownum" select="$rownum"/>
                            <xsl:with-param name="first_call" select="Y"/>
                        </xsl:call-template>
                    </table>
                    
                </td>
            </tr>
        </xsl:if>
    </xsl:template>

<xsl:template name="multi_instance_table_heading">
        <xsl:param name="rownum"/>
        <xsl:if test="//ROW[$rownum]/ELEMENT_CONTENT_ITERATION=1">
            <th align="left" bgcolor="#C6D9D8">
                <xsl:value-of select="//ROW[ROWNUM=($rownum)]/PROMPT"/>
            </th>
            <xsl:if test="//ROW[$rownum]/PROPOSAL_ELEMENT_CD=//ROW[($rownum)+1]/PROPOSAL_ELEMENT_CD">
                <xsl:call-template name="multi_instance_table_heading">
                    <xsl:with-param name="rownum" select="$rownum+1"/>
                </xsl:call-template>
            </xsl:if>
        </xsl:if>
    </xsl:template>
    
    <xsl:template name="multi_instance_table_row">
        <xsl:param name="rownum"/>
        <xsl:param name="first_call"/>
        <xsl:if test="$first_call='Y' or 
            ((//ROW[ROWNUM=($rownum)]/ELEMENT_CONTENT_ITERATION!=//ROW[ROWNUM=(($rownum)-1)]/ELEMENT_CONTENT_ITERATION) or 
            (//ROW[ROWNUM=($rownum)]/PROPOSAL_ELEMENT_CD!=//ROW[ROWNUM=(($rownum)-1)]/PROPOSAL_ELEMENT_CD))">
            <tr><td>HELLO BEN {PIE_SEQUENCE_NUMBER}</td></tr>
            <tr>
                <xsl:call-template name="do_padding">
                    <xsl:with-param name="pad_amount" select="//ROW[ROWNUM=($rownum)]/TREE_LEVEL"/>
                </xsl:call-template>
                <xsl:call-template name="multi_instance_table_column">
                    <xsl:with-param name="rownum" select="$rownum"/>
                </xsl:call-template>
                <xsl:for-each select="../ROW[SUP_PIE_SEQUENCE_NUMBER = current()/PIE_SEQUENCE_NUMBER]">
                    <!--- Output the new node. -->
                    <xsl:call-template name="multi_instance_table">
                        <xsl:with-param name="rownum" select="$rownum"/>
                    </xsl:call-template>            
                </xsl:for-each> 
            </tr>
        </xsl:if>
        <xsl:if test="//ROW[ROWNUM=($rownum)]/PROPOSAL_ELEMENT_CD=//ROW[ROWNUM=(($rownum)+1)]/PROPOSAL_ELEMENT_CD">
            <xsl:call-template name="multi_instance_table_row">
                <xsl:with-param name="rownum" select="$rownum+1"/>
                <xsl:with-param name="first_call" select="N"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
    
    <xsl:template name="multi_instance_table_column">
        <xsl:param name="rownum"/>
        <td align="left" style="padding:2px; border:1px; border-style:solid;">
            <xsl:call-template name="input_value">
                <xsl:with-param name="rownum" select="$rownum"/>
            </xsl:call-template> 
        </td>
        <xsl:if test="(//ROW[ROWNUM=($rownum)]/ELEMENT_CONTENT_ITERATION=//ROW[ROWNUM=(($rownum)+1)]/ELEMENT_CONTENT_ITERATION) and 
            (//ROW[ROWNUM=($rownum)]/PROPOSAL_ELEMENT_CD=//ROW[ROWNUM=(($rownum)+1)]/PROPOSAL_ELEMENT_CD)">
            <xsl:call-template name="multi_instance_table_column">
                <xsl:with-param name="rownum" select="$rownum+1"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

Open in new window



I'm no xpath or xsl expert and am more used to working with CSS and HTML than XML and XSL.  I would really appreciate it if I could get some advice.

I need to modify the template stuff so that, for anything with a path including MASTER, it will check to see if their are child records by determining if any following ROW/SUP_PIE_SEQUENCE_NUMBER matches the current ROW/PIE_SEQUENCE_NUMBER.  If so, I would like to recursively call the multi instance table template to render another table immediately following the parent row (i.e. as part of the parent row content).  However, alternate solutions would also be acceptible.

Any assistance here would be dearly appreciated.

thanks in advance

Ben
0
bentownsend
Asked:
bentownsend
  • 5
  • 4
1 Solution
 
Geert BormansCommented:
Likely you have a starting point for all ROW in your template for "/"

Be selctive there

    <xsl:template match="/">
        <table>
            <xsl:for-each select="ROWSET/ROW[not(normalize-space(SUP_PIE_SEQUENCE_NUMBER))]">
                <xsl:call-template name="multi_instance_table">
                    <xsl:with-param name="rownum" select="ROWNUM"/>
                </xsl:call-template>
            </xsl:for-each>
        </table>
    </xsl:template>

Now you only process the top rows

Then make a key (index) for finding rows efficiently based on the SUP_PIESEQUENCE_NULBER
    <xsl:key name="row-by-pie-seq" match="ROW" use="SUP_PIE_SEQUENCE_NUMBER"/>
(top of document that should be)

now, inside or outside the table (as you please) in the multi_instance_table  template
you can do this

                   <xsl:for-each select="key('row-by-pie-seq', PIE_SEQUENCE_NUMBER)">
                        <xsl:call-template name="multi_instance_table">
                            <xsl:with-param name="rownum" select="ROWNUM"/>
                        </xsl:call-template>
                    </xsl:for-each>
The for each selects all ROW that have the current pie seq number as their sup pie seq number (so it slects all virtual children)

That does what you need

0
 
Geert BormansCommented:
Looking in your stylesheet
you do a lot of this: //ROW[ROWNUM=($rownum)]
That is a very bad practice.
This means that every time you do this, the processor checks all ROW elements to get you back the correct ROW.
This is sooooooooooo slow
It is better to index that, using another key
   <xsl:key name="row-by-num" match="ROW" use="ROWNUM"/>

have a variable
        <xsl:variable name="row" select="key('row-by-num', $rownum)"/>
and use $row instead

                <xsl:when test="$row/S_FIELD_TYPE='CLOB'">

in your variable isempty I found some other mistakes

not(text()) is not what you want.
I think you are using msxml, because that has a bug that makes this work. It would fail on other processors likely
you test for having text() nodes, but a single space is a text node as well
you should change that test into [not(normalize-space(.))]

tests could be done more readable

here is my rewrite of the variable
Here is my rewrite of isempty


<xsl:variable name="row" select="key('row-by-num', $rownum)"/>
        
        <xsl:variable name="isempty">
            <xsl:choose>
                <xsl:when test="
                    $row[S_FIELD_TYPE='CLOB']/CLOB_VALUE[not(normalize-space(.))] 
                    |  $row[S_FIELD_TYPE='NUMBER']/NUMBER_VALUE[not(normalize-space(.))] 
                    |  $row[S_FIELD_TYPE='DATE']/DATE_VALUE[not(normalize-space(.))]
                    |  $row[not(S_FIELD_TYPE='CLOB' or S_FIELD_TYPE='NUMBER' or S_FIELD_TYPE='DATE')]/CHAR_VALUE[not(normalize-space(.))]
                    ">
                    true
                </xsl:when>
                <xsl:otherwise>
                    false
                </xsl:otherwise>
            </xsl:choose>
        </xsl:variable>

Open in new window

0
 
bentownsendAuthor Commented:
Hmmm, I tried this, but doing what you suggest in your first comment seems to make the transform go into an infinite loop.  Unfortunately, I did not create any of the XSL, so I am not clear on why things have been done how they have.  As usual, there's no doco.  Perhaps the full style sheet will help to see what the problem might be.  I attach the original style sheet below:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsd="http://www.w3.org/2000/10/XMLSchema"
>
  <xsl:template match="/">
    <h1>Print Proposal</h1>
    <table width="100%">
      <xsl:for-each select="//ROW[SUP_PROPOSAL_ELEMENT_CD='' and SUP_PIE_SEQUENCE_NUMBER='']">
        <xsl:call-template name="create_hierarchy">
          <xsl:with-param name="superior_element_cd" select="PROPOSAL_ELEMENT_CD"/>
          <xsl:with-param name="superior_element_seq_no" select="PIE_SEQUENCE_NUMBER"/>
        </xsl:call-template>
      </xsl:for-each>
    </table>
  </xsl:template>
  <xsl:template name="create_hierarchy">
    <xsl:param name="rownum" select="ROWNUM"/>
    <xsl:param name="superior_element_cd"/>
    <xsl:param name="superior_element_seq_no"/>
    <xsl:if test="$rownum=1 or (PROPOSAL_ELEMENT_CD != //ROW[($rownum)-1]/PROPOSAL_ELEMENT_CD)">
      <xsl:call-template name="element_heading"/>
    </xsl:if>
    <xsl:if test="ELEMENT_MULTIPLE_INST_IND='Y' and DELETE_IND='N'">
      <xsl:call-template name="multi_instance_table"/>
    </xsl:if>
    <xsl:if test="ELEMENT_MULTIPLE_INST_IND='N' and DELETE_IND='N'">
      <tr>
        <xsl:call-template name="do_padding">
          <xsl:with-param name="pad_amount" select="TREE_LEVEL"/>
        </xsl:call-template>
        <td align="left" style="padding:5px; border:1px; border-style:solid; width:20%;">
          <xsl:value-of select="PROMPT"/>
        </td>
        <td align="left" style="padding:5px; border:1px; border-style:solid;">
          <xsl:call-template name="single_instance_item">
            <xsl:with-param name="rownum" select="ROWNUM"/>
          </xsl:call-template>
        </td>
      </tr>
    </xsl:if>
    <xsl:if test="((PROPOSAL_ELEMENT_CD!=string(following::*/PROPOSAL_ELEMENT_CD[1])) or
(PIE_SEQUENCE_NUMBER!=string(following::*/PIE_SEQUENCE_NUMBER[1])))">
      <xsl:for-each select="//ROW[SUP_PROPOSAL_ELEMENT_CD=$superior_element_cd and SUP_PIE_SEQUENCE_NUMBER=$superior_element_seq_no]">
        <xsl:call-template name="create_hierarchy">
          <xsl:with-param name="superior_element_cd" select="PROPOSAL_ELEMENT_CD"/>
          <xsl:with-param name="superior_element_seq_no" select="PIE_SEQUENCE_NUMBER"/>
        </xsl:call-template>
      </xsl:for-each>
    </xsl:if>
  </xsl:template>
  <xsl:template name="do_padding">
    <xsl:param name="pad_amount"/>
    <td align="left" style="width:1%;">
      <div style="width:20px; height: 10px;"></div>
    </td>
    <xsl:if test="$pad_amount > 1">
      <xsl:call-template name="do_padding">
        <xsl:with-param name="pad_amount" select="($pad_amount)-1"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>
  <xsl:template name="element_heading">
    <tr>
      <td align="left" colspan="100">
        <br/>
      </td>
    </tr>
    <tr>
      <td align="left" colspan="100">
        <table width="100%">
          <tr>
            <xsl:call-template name="do_padding">
              <xsl:with-param name="pad_amount" select="TREE_LEVEL"/>
            </xsl:call-template>
            <th align="left" bgcolor="#83BAD4" style="padding:5px; border:1px; border-style:solid;">
              <xsl:value-of select="ELEMENT_HEADING"/>
            </th>
          </tr>
        </table>
      </td>
    </tr>
  </xsl:template>
  <xsl:template name="input_value">
    <xsl:param name="rownum"/>
    <xsl:choose>
      <xsl:when test="//ROW[ROWNUM=($rownum)]/S_FIELD_TYPE='CLOB'">
        <xsl:call-template name="ie7fix">
          <xsl:with-param name="data" select="//ROW[ROWNUM=($rownum)]/CLOB_VALUE"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="//ROW[ROWNUM=($rownum)]/S_FIELD_TYPE='NUMBER'">
        <xsl:call-template name="ie7fix">
          <xsl:with-param name="data" select="//ROW[ROWNUM=($rownum)]/NUMBER_VALUE"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="//ROW[ROWNUM=($rownum)]/S_FIELD_TYPE='DATE'">
        <xsl:call-template name="ie7fix">
          <xsl:with-param name="data" select="//ROW[ROWNUM=($rownum)]/DATE_VALUE"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:call-template name="ie7fix">
          <xsl:with-param name="data" select="//ROW[ROWNUM=($rownum)]/CHAR_VALUE"/>
        </xsl:call-template>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
  <xsl:template name="ie7fix">
    <xsl:param name="data"/>
    <xsl:choose>
      <xsl:when test="$data[not(text())]">
        <div id="ie7emptycellfix" style="width:10px; height:10px;"></div>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$data"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
  <xsl:template name="checkbox_radio_ticked_fix">
    <xsl:param name="rownum"/>
    <xsl:if test="//ROW[ROWNUM=($rownum)][CHAR_VALUE='Y'] | //ROW[ROWNUM=($rownum)][CLOB_VALUE='Y'] | //ROW[ROWNUM=($rownum)][NUMBER_VALUE='Y'] | //ROW[ROWNUM=($rownum)][DATE_VALUE='Y']">
      <xsl:attribute name="checked"/>
    </xsl:if>
  </xsl:template>
  <xsl:template name="single_instance_item">
    <xsl:param name="rownum"/>
    <xsl:choose>
      <xsl:when test="S_INPUT_FIELD_TYPE = 'CHECKBOX'">
        <xsl:call-template name="input_value">
          <xsl:with-param name="rownum" select="$rownum"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="S_INPUT_FIELD_TYPE = 'RADIO'">
        <xsl:call-template name="input_value">
          <xsl:with-param name="rownum" select="$rownum"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:call-template name="input_value">
          <xsl:with-param name="rownum" select="$rownum"/>
        </xsl:call-template>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
  <xsl:template name="multi_instance_table">
    <xsl:param name="rownum" select="ROWNUM"/>
    <xsl:variable name="isempty">
      <xsl:choose>
        <xsl:when test="//ROW[ROWNUM=($rownum)]/S_FIELD_TYPE='CLOB'">
          <xsl:choose>
            <xsl:when test="//ROW[ROWNUM=($rownum)]/CLOB_VALUE[not(text())]">true</xsl:when>
            <xsl:otherwise>false</xsl:otherwise>
          </xsl:choose>
        </xsl:when>
        <xsl:when test="//ROW[ROWNUM=($rownum)]/S_FIELD_TYPE='NUMBER'">
          <xsl:choose>
            <xsl:when test="//ROW[ROWNUM=($rownum)]/NUMBER_VALUE[not(text())]">true</xsl:when>
            <xsl:otherwise>false</xsl:otherwise>
          </xsl:choose>
        </xsl:when>
        <xsl:when test="//ROW[ROWNUM=($rownum)]/S_FIELD_TYPE='DATE'">
          <xsl:choose>
            <xsl:when test="//ROW[ROWNUM=($rownum)]/DATE_VALUE[not(text())]">true</xsl:when>
            <xsl:otherwise>false</xsl:otherwise>
          </xsl:choose>
        </xsl:when>
        <xsl:otherwise>
          <xsl:choose>
            <xsl:when test="//ROW[ROWNUM=($rownum)]/CHAR_VALUE[not(text())]">true</xsl:when>
            <xsl:otherwise>false</xsl:otherwise>
          </xsl:choose>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <xsl:if test="$rownum=1 or PROPOSAL_ELEMENT_CD != string(//ROW[($rownum)-1]/PROPOSAL_ELEMENT_CD)">
      <tr>
        <td align="left" colspan="100">
          <table spacing="0">
            <tr>
              <xsl:call-template name="do_padding">
                <xsl:with-param name="pad_amount" select="TREE_LEVEL"/>
              </xsl:call-template>
              <xsl:call-template name="multi_instance_table_heading">
                <xsl:with-param name="rownum" select="$rownum"/>
              </xsl:call-template>
            </tr>
            <xsl:call-template name="multi_instance_table_row">
              <xsl:with-param name="rownum" select="$rownum"/>
              <xsl:with-param name="first_call" select="Y"/>
            </xsl:call-template>
          </table>
        </td>
      </tr>
    </xsl:if>
  </xsl:template>
  <xsl:template name="multi_instance_table_heading">
    <xsl:param name="rownum"/>
    <xsl:if test="//ROW[$rownum]/ELEMENT_CONTENT_ITERATION=1">
      <th align="left" bgcolor="#C6D9D8">
        <xsl:value-of select="//ROW[ROWNUM=($rownum)]/PROMPT"/>
      </th>
      <xsl:if test="//ROW[$rownum]/PROPOSAL_ELEMENT_CD=//ROW[($rownum)+1]/PROPOSAL_ELEMENT_CD">
        <xsl:call-template name="multi_instance_table_heading">
          <xsl:with-param name="rownum" select="$rownum+1"/>
        </xsl:call-template>
      </xsl:if>
    </xsl:if>
  </xsl:template>
  <xsl:template name="multi_instance_table_row">
    <xsl:param name="rownum"/>
    <xsl:param name="first_call"/>
    <xsl:if test="$first_call='Y' or 
((//ROW[ROWNUM=($rownum)]/ELEMENT_CONTENT_ITERATION!=//ROW[ROWNUM=(($rownum)-1)]/ELEMENT_CONTENT_ITERATION) or 
(//ROW[ROWNUM=($rownum)]/PROPOSAL_ELEMENT_CD!=//ROW[ROWNUM=(($rownum)-1)]/PROPOSAL_ELEMENT_CD))">
      <tr>
        <xsl:call-template name="do_padding">
          <xsl:with-param name="pad_amount" select="//ROW[ROWNUM=($rownum)]/TREE_LEVEL"/>
        </xsl:call-template>
        <xsl:call-template name="multi_instance_table_column">
          <xsl:with-param name="rownum" select="$rownum"/>
        </xsl:call-template>
      </tr>
    </xsl:if>
    <xsl:if test="//ROW[ROWNUM=($rownum)]/PROPOSAL_ELEMENT_CD=//ROW[ROWNUM=(($rownum)+1)]/PROPOSAL_ELEMENT_CD">
      <xsl:call-template name="multi_instance_table_row">
        <xsl:with-param name="rownum" select="$rownum+1"/>
        <xsl:with-param name="first_call" select="N"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>
  <xsl:template name="multi_instance_table_column">
    <xsl:param name="rownum"/>
    <td align="left" style="padding:2px; border:1px; border-style:solid;">
      <xsl:call-template name="input_value">
        <xsl:with-param name="rownum" select="$rownum"/>
      </xsl:call-template>
    </td>
    <xsl:if test="(//ROW[ROWNUM=($rownum)]/ELEMENT_CONTENT_ITERATION=//ROW[ROWNUM=(($rownum)+1)]/ELEMENT_CONTENT_ITERATION) and 
(//ROW[ROWNUM=($rownum)]/PROPOSAL_ELEMENT_CD=//ROW[ROWNUM=(($rownum)+1)]/PROPOSAL_ELEMENT_CD)">
      <xsl:call-template name="multi_instance_table_column">
        <xsl:with-param name="rownum" select="$rownum+1"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

Open in new window

0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
Geert BormansCommented:
there is already non working hierarchy code in your stylesheet, you should remove that

How bad is it with your XSLT knowledge?

There are some unknowns in this question, but I am not going to simply rewrite this stuff myself as part of an EE question
0
 
Geert BormansCommented:
what I want to say is, that the analysis of what is doing what in the code is taking me too far.

what you need to do is comment the code for creating hierarchy etc. out and use the template match="/" as I suggested
Also make sure that the stuff with preceding - 1 etc gets removed

I recommend that you use my suggested key approach as a framework and build the rest around it
(I know, lot of work)

keys is the only certain way to deal with this in a hierarchical fashion
but the required rewrite is too much for an EE question
(I will definitely not do it just like that)
So my advice: either learn enough XSLT to get the job done or hire assitance
0
 
bentownsendAuthor Commented:
Gertone,

Thanks for the advice.  I appreciate it

However, I just want to clarify.  I was not asking for a rewrite, just a pointer to which sections may have been causing the issues with infinite looping once your suggestions were also implemented into the XSL.  I am not an XSLT specialist, as noted in my original question, and while the advice parts of your answer are certainly helpful, the sarcasm parts ("How bad is it with your XSLT knowledge?") are not helpful at all, and may serve to alienate users of this service.  I just don't I think it was necessary to include these.

I am quite happy to try this myself, or to pay someone to do it if it is beyond my abilities, so if you want my advice for your self-assumed role as an expert on EE, please don't assume I just want a rewrite, and try and stay focussed on the issue at hand.

Again, your advice was useful, so thanks for your help, and I will see what I can do.
0
 
bentownsendAuthor Commented:
Thanks
0
 
Geert BormansCommented:
Dear Ben,

If I gave the impression of uttering any sarcasm, I really do apologize.
I was not being sarcastic at all, or definitely did not want to be.
I was honestly providing you with the options I think you have.

I have never assumed you would want me to rewrite your stuff,
but when I step into a question, I don't give up before the issue is resolved.
(Please check some of my earlier answers to see how far I sometimes go to help)
Maybe I just expressed in a wrong way that I felt I was not helping you enough, but had too little real options left.

I was concerned. You indicated not being an XSLT specialist.
From that I concluded that you are worried about taking on complex tasks.
That is why I asked "how bad is your XSLT?"
I should have asked "how good is it?", maybe.
I was just trying to find out whether or not you would feel up to the task of starting the rewrite that I suggested

To my defence, my mother tongue is not English, and sometimes my responses are written in haste.
This might influence the tone of the messages I write.
Note that if you would directly translate my question to Flemish Dutch (my mother tongue) there would be no sarcasm at all in my question.
But I accept your advice, and will in future be more careful about the tone of my messages
Again, my sincere apologies for this.

There is some hierarchy code in your code already.
I see what it tries to do, and I see why it breaks the nested approach.
But I don't fully understand why it is written that way, so I feel very reluctant about giving the advice of throwing it all out
If this were my project, I would start from scratch building up the hierarchy (using my code) first as this is the skeleton of your end result.
Then I would add the parts I need from the old code incrementally.
But this would be quite a task.

I also just wanted to indicate that Experts Exchange is here to help you help yourself.
Some do come here with the expectation of receiving a complete rewrite of the code as a result of this service.
Sometimes I even do.
I wanted to make sure that you did not have this expectations, since I guess that doing this for you would take me a couple of hours

Please accept that I was not patronizing at all.
I was just trying to find out whether or not my advice would help you or would just make you walk away from the advice, simply because my suggestion was above your experience level.
(I do hope I phrase this right)

Anyway, I do hope that you follow the path of my suggestion,
it will lead to the best result in the end... but will be quite a task now.

If you start this task, please don't be afraid of returning to this question once you are stuck.
I would be glad to help you with the next step.
If you feel this is beyond your experience level, don't hesitate to write me an email, we might figure something out, off line.

Anyway, I can't apologize enough for hurting your feelings and do wish you all the best with this project

Geert
0
 
bentownsendAuthor Commented:
Geert

you are a champion, and one of the reasons why Experts Exchange is so successful.  In fact, the stuff you proposed has given me the grounding to throw away the provided stylesheet and try writing something based on what you wrote, to address the real issue.

At the end of the day, all I can offer is my gratitude - maybe I can sum up be saying:

Thanks for your help - it pointed me in the right direction!

Ben
0

Featured Post

[Webinar On Demand] Database Backup and Recovery

Does your company store data on premises, off site, in the cloud, or a combination of these? If you answered “yes”, you need a data backup recovery plan that fits each and every platform. Watch now as as Percona teaches us how to build agile data backup recovery plan.

  • 5
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now