2013-02-21 171 views
0

我想用XSLT构建评论系统。下面是已经提交评论XML输入:XSLT评论系统

<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> 

如果有人可以把我在正确的我非常感谢它。如果需要更多信息,请告诉我。实际的模板“评论”只是简单地将评论传递给它并按照我想要的方式进行格式化。

回答

2

而不是使用的xsl:for-每个,然后到指定的模板通话时,您可以考虑两者结合成一个XSL:申请模板通话。首先,你会选择用0

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

然后,ResponseCommentID属性的意见,你将有一个模板来匹配评论属性,在这里你将输出注释细节。然后,您可以递归得到的回应意见,像这样:

<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> 
+0

真棒蒂姆。感谢您的回应。我对密钥不太熟悉,但您的解决方案完全符合我期望的要求!我还应该提到使用缩进列表非常聪明。我不知道为什么我没有想到这一点。 – user673869 2013-02-25 18:51:48

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> 

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

 <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> 

还是不完全理解它(我一直不得不重播一系列事件在我脑海中),但我相信这是有效的。 :)