Cory Foy

Tuesday, November 23, 2004

Creating a threaded comment generator with XSL

I got an email from a friend of mine who is building a BBS app that he wants to have threaded comments. Basically:

- This is the top post
   - This is the reply to the top
      - This is the reply to the reply

He's using classic ASP, and was looking for a way to avoid having to do a recursive query to get the information. At first I was thinking of some SQL strategies to help avoid it but then thought that XML might be a good answer to it.

XML Document:


<?xml version="1.0"?>
<threads>
   <thread id="45" parent="">
      <title>Top Level Thread</title>
      <message>I'm a top level thread</message>
   </thread>
   <thread id="49" parent="">
      <title>Top Level Thread2</title>
      <message>I'm a top level2 thread</message>
   </thread>
   <thread id="46" parent="45">
      <title>Mid Level Thread</title>
      <message>I'm a mid level thread</message>
   </thread>
   <thread id="47" parent="45">
      <title>Mid Level Thread</title>
      <message>I'm a mid level thread</message>
   </thread>
   <thread id="48" parent="46">
      <title>Mid Level Thread</title>
      <message>I'm a mid level thread</message>
   </thread>
   <thread id="50" parent="49">
      <title>Mid Level Thread</title>
      <message>I'm a mid level thread</message>
   </thread>
   <thread id="54" parent="">
      <title>Top Level Thread3</title>
      <message>I'm a top level3 thread</message>
   </thread>
</threads>


XSL Document:

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

<xsl:template match="/">
   <html>
      <head>
         <title>Cool BBS</title>
      </head>
      <body>
         <h1>Here is some cool BBS type stuff:</h1>
         <xsl:apply-templates select="threads"/>
      </body>
   </html>
</xsl:template>

<xsl:template match="threads">
   <ul>
   <xsl:for-each select="thread[@parent = '']">
      <li><xsl:value-of select="title"/></li>
      <xsl:call-template name="thread">
         <xsl:with-param name="parentid"><xsl:value-of select="@id"/></xsl:with-param>
      </xsl:call-template>
   </xsl:for-each>
   </ul>
</xsl:template>

<xsl:template name="thread">
   <xsl:param name="parentid"/>
   <ul>
   <xsl:for-each select="/threads/thread[@parent=$parentid]">
      <li><xsl:value-of select="title"/></li>
      <xsl:call-template name="thread">
         <xsl:with-param name="parentid"><xsl:value-of select="@id"/></xsl:with-param>
      </xsl:call-template>
   </xsl:for-each>
   </ul>
</xsl:template>

</xsl:stylesheet>


Output:

<ul>
 <li>I'm a top level thread</li>
 <ul>
   <li>Mid Level Thread</li>
   <ul>
      <li>Mid Level Thread</li>
   </ul>
   <li>Mid Level Thread</li>
 </ul>
</ul>


0 Comments:

Post a Comment

Links to this post:

Create a Link

<< Home