iskinner 0 Newbie Poster

Thanks to some great help for my first ever post on this formum [
Fetch a node based on a value of another node.] I am now recursively traversing through my XML data where nodes are related to each other.

Example XML

<gedcom>
  <INDI ID="@I001@">
    ...
    <FAMC>@F001@</FAMC>
  </INDI>
  <INDI ID="@I002@">
    ...
    <FAMC>@F002@</FAMC>
  </INDI>
  <INDI ID="@I003@">
    ...
    <FAMC>@F003@</FAMC>
  </INDI>
  ...
  <FAM ID="@F001@</FAM>
    ...
    <HUSB>@I002@</HUSB>
    <WIFE>@I003@</WIFE>
  </FAM>
  <FAM ID="@F002@</FAM>
    ...
    <HUSB>@I004@</HUSB>
    <WIFE>@I005@</WIFE>
  </FAM>
  <FAM ID="@F003@</FAM>
    ...
    <HUSB>@I006@</HUSB>
    <WIFE>@I007@</WIFE>
  </FAM>
  ...
</gedcom>

Here is my current XSLT code

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="html"/>

<xsl:template match="/">
  <html>
    <head>
      <title>Pedigree Chart</title>
    </head>
    <body>
      <table>
        <tr>
        <xsl:apply-templates select="/gedcom/INDI[@ID='@I001@']">
          <xsl:with-param name="generation">0</xsl:with-param>
        </xsl:apply-templates>
        </tr>
      </table>
    </body>
  </html>
</xsl:template>
	
<xsl:template match="INDI">
  <xsl:param name="generation"/>

    <td>
      <xsl:value-of select="$generation"/>
      <xsl:value-of select="./NAME/text()"/><br/>
    </td>
    <xsl:apply-templates select="FAMC">
      <xsl:with-param name="generation">
        <xsl:value-of select="$generation"/>
      </xsl:with-param>
    </xsl:apply-templates>
</xsl:template>
	
<xsl:template match="FAMC">
  <xsl:param name="generation"/>
  <xsl:if test="$generation &lt; 4">
    <xsl:variable name="data" select="."/>
    <xsl:apply-templates select="../../FAM[@ID=$data]">
      <xsl:with-param name="generation">
        <xsl:value-of select="$generation + 1"/>
      </xsl:with-param>
    </xsl:apply-templates>
  </xsl:if>
</xsl:template>

<xsl:template match="FAM">
  <xsl:param name="generation"/>
  <xsl:apply-templates select="HUSB|WIFE">
    <xsl:with-param name="generation">
      <xsl:value-of select="$generation"/>
    </xsl:with-param>
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="HUSB|WIFE">
  <xsl:param name="generation"/>
  <xsl:variable name="data" select="."/>
  <xsl:apply-templates select="../../INDI[@ID=$data]">
    <xsl:with-param name="generation">
      <xsl:value-of select="$generation"/>
    </xsl:with-param>
  </xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>

This produces all the desired xml nodes in the output, but they are all in a single table row. What I desire is a table row once each 5th generation is reached ($generations = 4).

It should look something like this:

<table>
  <tr>
    <td rowspan="16">generation 0</td>
    <td rowspan="8">generation 1</td>
    <td rowspan="4">generation 2</td>
    <td rowspan="2">generation 3</td>
    <td rowspan="1">generation 4</td>
  </tr>
  <tr>
    <td rowspan="1">generation 4</td>
  </tr>
  <tr>
    <td rowspan="2">generation 3</td>
    <td rowspan="1">generation 4</td>
  </tr>
  <tr>
    <td rowspan="1">generation 4</td>
  </tr>
  <tr>
    <td rowspan="4">generation 2</td>
    <td rowspan="2">generation 3</td>
    <td rowspan="1">generation 4</td>
  </tr>
  <tr>
    <td rowspan="1">generation 4</td>
  </tr>
  <tr>
    <td rowspan="2">generation 3</td>
    <td rowspan="1">generation 4</td>
  </tr>
  <tr>
    <td rowspan="1">generation 4</td>
  </tr>
  ...
</table>

I have XSLT logic to properly calculate the rowspan attributes of each cell and to substitute content of the <td></td> nodes with actual data from the XML document. But I have no idea how to properly wrap the correct number of cells in <tr></tr> table rows.

I tried a trick I often use in procedural programming, but the XSLT parser did not like it as it does not properly nest tags.

<xsl:template match="INDI">
  <xsl:param name="generation"/>

    <td>
      <xsl:value-of select="$generation"/>
      <xsl:value-of select="./NAME/text()"/><br/>
    </td>
    <xsl:apply-templates select="FAMC">
      <xsl:with-param name="generation">
        <xsl:value-of select="$generation"/>
      </xsl:with-param>
    </xsl:apply-templates>

  <xsl:if test="$generation = 4">
    <!-- reached the end of a row, close the current row tag and open a new row -->
    </tr>
    <tr>
  </xsl:if>
</xsl:template>

Can anybody guide me to the XSLT method to do this type of logic.

TIA
Ian

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.