954,517 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

tags|nodes with conditional content

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 nodes with actual data from the XML document. But I have no idea how to properly wrap the correct number of cells in 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

iskinner
Newbie Poster
6 posts since Feb 2011
Reputation Points: 10
Solved Threads: 0
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You
View similar articles that have also been tagged: