xsl-list
[Top] [All Lists]

RE: Urgent Help Needed in XSLT

2002-09-23 08:31:34
Hi Yan,

My understand is that "descendant-or-self" should be used instead of
"ancestor-or-self" as we need to get one lastest children or self
llnode
from the same topic.  If this is true, I also need to change the first
"for-each":

I don't think so?  Depends on what you are trying to achieve.
If you want to find all the latest message dates for each distinct topic
(distinct by the topic name, e.g. @name) then you want ancestor-or-self
- because you are looking for the distinct name of the overall thread
rather than any of the reply topic names (e.g. name="Re: Topic 1").

Actually though, looking again at my code maybe it is a bit
over-complicated.  If each thread start element (llnode) is an immediate
child of the root element <livelink> then we need not find all distinct
topic names at all?  And just go through the livelink/llnode elements,
e.g.

== XSL =================================================
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
<xsl:output method="html" indent="yes"/>
<xsl:template match="livelink">
  <!-- create a list of (node ids) for each distinct topic -->
  <!-- with the id of the latest message in that thread   -->
  <xsl:variable name="sorted-topic-dates">
    <!-- find all topic (top) thread starts -->
    <xsl:for-each select="llnode">
      <!-- sort this and descendant children by their descending date
-->
      <xsl:for-each select="descendant-or-self::llnode">
        <xsl:sort select="@created" order="descending"/>
        <!-- output a reference to this node if it the latest in this
'thread' -->
        <xsl:if test="position() = 1">
          <xsl:text>|</xsl:text>
          <xsl:value-of select="generate-id()"/>
        </xsl:if>
      </xsl:for-each>
    </xsl:for-each>
  </xsl:variable>
  <html>
    <body>
      <table>
        <!-- go through all nodes where they appear in the distinct
topic dates variable -->
        <xsl:for-each
select=".//llnode[contains($sorted-topic-dates,concat('|',generate-id())
)]">
          <!-- sort them on date descending -->
          <xsl:sort select="@created" order="descending"/>
          <!-- only show the first 10 -->
          <xsl:if test="position() &lt; 11">
            <tr>
              <td>
                <xsl:value-of
select="ancestor-or-self::llnode[last()]/@name"/>
              </td>
              <td>
                <xsl:value-of select="@created"/>
              </td>
              <td>
                <xsl:choose>
                  <xsl:when test="ancestor::llnode">
                    <xsl:text> (Reply)</xsl:text>
                  </xsl:when>
                  <xsl:otherwise>
                    <xsl:text> (New Topic)</xsl:text>
                  </xsl:otherwise>
                </xsl:choose>
              </td>
            </tr>
          </xsl:if>
        </xsl:for-each>
      </table>
    </body>
  </html>
</xsl:template>
</xsl:stylesheet>
== end of XSL ==========================================

I think the reason I made the first one so complicated was to cater for
the possibility that threads may not be maintained as hierarchical
structures in the XML (e.g. in case, like some newsgroups do, the
original thread start gets dropped after a period).

Cheers
Marrow

-----Original Message-----
From: owner-xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
[mailto:owner-xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com] On Behalf Of 
Kong, Yan
Sent: 23 September 2002 15:57
To: 'xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com'
Subject: RE: [xsl] Urgent Help Needed in XSLT

Marrow,

I really appreciate your reply.  I think you have understood what I
want.  I need to display the latest top 10 discussion topics in HTML
which have either the latest reply or latest new topic.  

I'm a beginner of XSLT, just started to read Michael Kay's XSLT
Programmer's Reference two weeks ago.  This is a totally different
concept for me from other programming language.  I have one question
regarding your codes:

         <xsl:key name="kDistinctTopic" match="/livelink//llnode"
use="ancestor-or-self::llnode[last()]/@name"/>

My understand is that "descendant-or-self" should be used instead of
"ancestor-or-self" as we need to get one lastest children or self llnode
from the same topic.  If this is true, I also need to change the first
"for-each":

    <xsl:for-each select=".//llnode[generate-id() =

generate-id(key('kDistinctTopic',ancestor-or-self::llnode[last()]/@name)

)]">

Replace "ancestor-or-self" to "descendant-or-self", am I right?

Thanks a lot,
Yan

----------
From:         Marrow[SMTP:marrow(_at_)marrowsoft(_dot_)com]
Reply To:     xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Sent:         Friday, September 20, 2002 6:16 PM
To:   xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject:      RE: [xsl] Urgent Help Needed in XSLT

Hi Yan,

Do you mean something like Google groups does?

Try this (not sure if it does what you want)...

== XSL ====================================================
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
<xsl:output method="html" indent="yes"/>
<xsl:key name="kDistinctTopic" match="/livelink//llnode"
use="ancestor-or-self::llnode[last()]/@name"/>  (question 1)
<xsl:template match="livelink">
  <!-- create a list of (node ids) for each distinct topic -->
  <!-- with the id of the latest message in that thread   -->
  <xsl:variable name="sorted-topic-dates">
    <!-- find the distinct topics -->
    <xsl:for-each select=".//llnode[generate-id() =

generate-id(key('kDistinctTopic',ancestor-or-self::llnode[last()]/@name)
(question 1)
)]">
      <!-- sort this and descendant children by their descending date
-->
      <xsl:for-each select="descendant-or-self::llnode">
        <xsl:sort select="@created" order="descending"/>
        <!-- output a reference to this node if it the latest in this
'thread' -->
        <xsl:if test="position() = 1">
          <xsl:text>|</xsl:text>
          <xsl:value-of select="generate-id()"/>
        </xsl:if>
      </xsl:for-each>
    </xsl:for-each>
  </xsl:variable>
  <html>
    <body>
      <table>
        <!-- go through all nodes where they appear in the distinct
topic dates variable -->
        <xsl:for-each

select=".//llnode[contains($sorted-topic-dates,concat('|',generate-id())
)]">
          <!-- sort them on date descending -->
          <xsl:sort select="@created" order="descending"/>
          <!-- only show the first 10 -->
          <xsl:if test="position() &lt; 11">
            <tr>
              <td>
                <xsl:value-of
select="ancestor-or-self::llnode[last()]/@name"/>
              </td>
              <td>
                <xsl:value-of select="@created"/>
              </td>
              <td>
                <xsl:choose>
                  <xsl:when test="ancestor::llnode">
                    <xsl:text> (Reply)</xsl:text>
                  </xsl:when>
                  <xsl:otherwise>
                    <xsl:text> (New Topic)</xsl:text>
                  </xsl:otherwise>
                </xsl:choose>
              </td>
            </tr>
          </xsl:if>
        </xsl:for-each>
      </table>
    </body>
  </html>
</xsl:template>
</xsl:stylesheet>
== end of XSL =============================================

Hope this helps
Marrow 
http://www.marrowsoft.com>  - home of Xselerator (XSLT IDE and
debugger)
http://www.topxml.com/Xselerator



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list



<Prev in Thread] Current Thread [Next in Thread>