XSLT评论系统

时间:2013-02-21 22:05:17

标签: xslt xslt-1.0

我正在尝试使用XSLT构建评论系统。这是已经提交的评论的XML输入:

<in:inputs xmlns:in="http://www.composite.net/ns/transformation/input/1.0">
<!-- Input Parameter, XPath /in:inputs/in:param[@name='story_id'] -->
<in:param name="story_id">182485599</in:param>
<!-- Function Call Result (0 ms), XPath /in:inputs/in:result[@name='LoggedInWebUserID'] -->
<in:result name="LoggedInWebUserID">233459</in:result>
<!-- Function Call Result (9 ms), XPath /in:inputs/in:result[@name='XML_Comment']/root -->
<in:result name="XML_Comment">
    <root xmlns="">
        <Comments CommentID="1" ResponseCommentID="0" WebUserID="123456" FULL_NAME="Osikhuemhe Abulume" Comment="test comment!!!!" DateSubmitted="Feb 20 2013  1:34PM"/>
        <Comments CommentID="2" ResponseCommentID="0" WebUserID="261337" FULL_NAME="Phillip Lowe" Comment="test comment2!!!!" DateSubmitted="Feb 20 2013  5:14PM"/>
        <Comments CommentID="3" ResponseCommentID="1" WebUserID="000007" FULL_NAME="Norman Abbott" Comment="my response" DateSubmitted="Feb 20 2013  5:14PM"/>
        <Comments CommentID="4" ResponseCommentID="0" WebUserID="233459" FULL_NAME="Tamara Failor" Comment="Not impressed..." DateSubmitted="Feb 20 2013  4:10PM"/>
        <Comments CommentID="5" ResponseCommentID="0" WebUserID="233459" FULL_NAME="Tamara Failor" Comment="blah blah blah. " DateSubmitted="Feb 20 2013  4:11PM"/>
        <Comments CommentID="6" ResponseCommentID="0" WebUserID="233459" FULL_NAME="Tamara Failor" Comment="dfsfs" DateSubmitted="Feb 20 2013  4:14PM"/>
        <Comments CommentID="7" ResponseCommentID="5" WebUserID="233459" FULL_NAME="Tamara Failor" Comment="this is a response to blah blah blah." DateSubmitted="Feb 20 2013  4:52PM"/>
        <Comments CommentID="8" ResponseCommentID="3"  WebUserID="233459" FULL_NAME="Tamara Failor" Comment="I don't agree with Norman. Terrible response." DateSubmitted="Feb 20 2013  5:39PM"/>
        <Comments CommentID="9" ResponseCommentID="4"  WebUserID="233459" FULL_NAME="Tamara Failor" Comment="I'm impressed." DateSubmitted="Feb 20 2013  5:43PM"/>
        <Comments CommentID="10" ResponseCommentID="1" WebUserID="233459" FULL_NAME="Tamara Failor" Comment="I've got something to say!" DateSubmitted="Feb 20 2013  6:34PM"/>
    </root>
</in:result>

这应该像新闻故事的任何其他评论系统一样(参见:http://www.npr.org/2013/02/20/172384724/when-a-bad-economy-means-working-forever

那就是 - 新的评论(ResponseCommentID = 0)总是被推到左边。

对这些评论的回复将在下面缩进。 (我现在不关心缩进。我希望得到评论的答复,以便彼此之下)

有两个部分我被卡住了。第一部分是如何调用每个帖子:

    <xsl:variable name="story_id" select="/in:inputs/in:param[@name='story_id']" />
    <xsl:variable name="root" select="/in:inputs/in:result[@name='XML_Comment']/root" />
    <xsl:for-each select="$root/Comments[@ResponseCommentID=0]">

    <!-- call the template to plot the first comment down -->
        <xsl:call-template name="thecomment">
            <xsl:with-param name="CommentID"><xsl:value-of select="@CommentID" /></xsl:with-param>
            <xsl:with-param name="ResponseCommentID"><xsl:value-of select="@ResponseCommentID" /></xsl:with-param>
        </xsl:call-template>

    <!-- if the comment has any responses, put those underneath the root -->
        <xsl:for-each select="$root/Comments[current()/@CommentID = $root/Comments/@ResponseCommentID]">
            <xsl:call-template name="thecomment">
                <xsl:with-param name="CommentID"><xsl:value-of select="@CommentID" /></xsl:with-param>
                <xsl:with-param name="ResponseCommentID"><xsl:value-of select="@ResponseCommentID" /></xsl:with-param>
            </xsl:call-template>
        </xsl:for-each>

模板的(也是非常错误的)结束递归部分:

    <xsl:if test="@CommentID = $root/Comments/@ResponseCommentID">
       <xsl:call-template name="thecomment">
            <xsl:with-param name="CommentID"><xsl:attribute name="value"><xsl:value-of select="@CommentID[@CommentID = $root/Comments/@ResponseCommentID]" /></xsl:with-param>
            <xsl:with-param name="ResponseCommentID"><xsl:attribute name="value"><xsl:value-of select="@ResponseCommentID[@CommentID = $root/Comments/@ResponseCommentID]" /></xsl:with-param>
        </xsl:call-template>
    </xsl:if>

如果有人能把我推向正确的方向,我会非常感激。如果需要更多信息,请告诉我。实际模板“thecomment”只是将评论传递给它并按照我喜欢的方式对其进行格式化。

2 个答案:

答案 0 :(得分:2)

您可以考虑将两者合并为一个 xsl:apply-templates 调用,而不是使用 xsl:for-each 然后调用命名模板。首先,您应选择ResponseCommentID属性为0的注释。

<xsl:apply-templates 
   select="in:inputs/in:result[@name='XML_Comment']/root/Comments[@ResponseCommentID='0']" />

然后,您将拥有一个匹配评论属性的模板,您可以在其中输出评论详细信息。然后,您可以递归地获取响应注释,如下所示:

<xsl:apply-templates select="../Comments[@ResponseCommentID = current()/@CommentID]" />

这将只是递归调用相同的评论模板,直到没有更多的回复。

在这种情况下,这是完整的XSLT(我将HTML中的注释作为列表项输出)作为示例

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:in="http://www.composite.net/ns/transformation/input/1.0" exclude-result-prefixes="in">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="/">
      <ul>
      <xsl:apply-templates select="in:inputs/in:result[@name='XML_Comment']/root/Comments[@ResponseCommentID='0']" />
      </ul>
   </xsl:template>

      <xsl:template match="Comments">
      <li>
         <xsl:value-of select="@Comment" />
         <xsl:if test="../Comments[@ResponseCommentID = current()/@CommentID]">
            <ul>
               <xsl:apply-templates select="../Comments[@ResponseCommentID = current()/@CommentID]" />
            </ul>
         </xsl:if>
      </li>
   </xsl:template>
</xsl:stylesheet>

这给出了以下输出

<ul>
   <li>test comment!!!!
      <ul>
         <li>my response
            <ul>
               <li>I don't agree with Norman. Terrible response.</li>
            </ul>
         </li>
         <li>I've got something to say!</li>
      </ul>
   </li>
   <li>test comment2!!!!</li>
   <li>Not impressed...
      <ul>
         <li>I'm impressed.</li>
      </ul>
   </li>
   <li>blah blah blah. 
      <ul>
         <li>this is a response to blah blah blah.</li>
      </ul>
   </li>
   <li>dfsfs</li>
</ul>

但是,在此处使用 xsl:key 来查找对评论的回复会更有效:

<xsl:key name="Comments" match="Comments" use="@ResponseCommentID" />

然后,要获得顶级评论,您可以这样做:

<xsl:apply-templates select="key('Comments', '0')" />

要获得匹配模板中给定评论的回复,您可以执行此操作

<xsl:apply-templates select="key('Comments', @CommentID)" />

以下XSLT也给出了相同的结果

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:in="http://www.composite.net/ns/transformation/input/1.0" exclude-result-prefixes="in">
   <xsl:output method="xml" indent="yes"/>

   <xsl:key name="Comments" match="Comments" use="@ResponseCommentID" />

   <xsl:template match="/">
      <ul>
      <xsl:apply-templates select="key('Comments', '0')" />
      </ul>
   </xsl:template>

      <xsl:template match="Comments">
      <li>
         <xsl:value-of select="@Comment" />
         <xsl:if test="key('Comments', @CommentID)">
            <ul>
               <xsl:apply-templates select="key('Comments', @CommentID)" />
            </ul>
         </xsl:if>
      </li>
   </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:0)

我想我明白了。这是我的XLST现在的样子。它将通过所有评论,但只有它是第一篇文章(@ResponseCommentID = 0)。

<xsl:for-each select="$root/Comments">

<xsl:if test="@ResponseCommentID = 0 and @CommentID != $root/Comments/@ResponseCommentID">
    <!-- call the template to first plot the comment down -->
        <xsl:call-template name="thecomment">
            <xsl:with-param name="CommentID"><xsl:value-of select="@CommentID" /></xsl:with-param>
            <xsl:with-param name="ResponseCommentID"><xsl:value-of select="@ResponseCommentID" /></xsl:with-param>
        </xsl:call-template>
</xsl:if>
</xsl:for-each>

这是最后的递归部分。它查看所有注释,并为每个@ResponseCommentID属性调用模板,该属性等于当前的@CommentID。

        <xsl:for-each select="$root/Comments[@ResponseCommentID = current()/@CommentID]">
       <xsl:call-template name="thecomment">
            <xsl:with-param name="CommentID"><xsl:value-of select="@CommentID" /></xsl:with-param>
            <xsl:with-param name="ResponseCommentID"><xsl:value-of select="@ResponseCommentID" /></xsl:with-param>
        </xsl:call-template>
    </xsl:for-each>

仍然不完全理解它(我不得不重播我头脑中的事件序列),但我相信这有效。 :)