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) は常に左側にプッシュされます。

これらのコメントへの応答は、下にインデントされます。(今はインデントは気にしません。コメントへの返信が互いに下に落ちるようにしたいと思います)

私が立ち往生している2つの部分があります。最初の部分は、各投稿の呼び出し方法です。

    <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」は、渡されたコメントを単純に取得し、希望どおりにフォーマットしています。

4

2 に答える 2

2

xsl:for-eachを使用してから名前付きテンプレートを呼び出すのではなく、2 つを 1 つのxsl:apply-templates呼び出しに結合することを検討できます。まず、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>
于 2013-02-21T23:20:07.233 に答える
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>

まだ完全には理解できていませんが (一連のイベントを頭の中で再生し続けなければなりません)、これでうまくいくと信じています。:)

于 2013-02-21T23:08:40.733 に答える