1

私の問題:
アトムRSSフィードファイルが豊富にあり、その中には多くの異なるアトムエントリがあり、ファイル間でいくつかの重複するエントリがあります。RSSフィードのいずれかからのURLに基​​づいてエントリを見つけて返す必要があります。

テクノロジー:
このコードは、XSLT1を使用するPHP5.2.10のXLSTProcessor拡張機能を介して実行され、EXSLTをサポートし、組み込みのPHP関数を実行する機能を備えています。Saxan、Xalan、または他の同様のソリューションは、この特定の状況ではあまり役に立ちません。

次のコードは大幅に簡略化されていますが、私の状況を表しています。

rss-feed-names.xml:

<feeds>
    <feed name="travel.xml"/>
    <feed name="holidays.xml"/>
    ...
    <feed name="summer.xml"/>
    <feed name="sports.xml"/>
</feeds>

stylesheet.xsl

<xsl:stylesheet ...>
...

<func:function name="cozi:findPost">
    <xsl:param name="post-url"/>  

    <xsl:variable name="blog-feeds" select="document('rss-feed-names.xml')/feeds"/>  

    <xsl:for-each select="$blog-feeds/feed">
        <xsl:variable name="feed-file" select="document(@name)/atom:feed"/>
        <xsl:variable name="feed-entry" select="$feed-file/atom:entry[atom:link[contains(@href, $post-url)]]"/>
        <xsl:if test="$feed-entry">
            <func:result select="$feed-entry"/><!-- this causes errors if more than one result is found -->
        </xsl:if>
    </xsl:for-each>
</func:function>
</xsl:stylesheet>
...

このコードは、探しているアトムエントリが、調べているファイルの1つに表示されている場合に問題なく機能します。そのファイル内に複数回表示される場合がありますが、2つ以上のファイルに表示されるとすぐに、func:resultが既にインスタンス化されて上書きされているため、コードが壊れます。これはXSLTではノーノーです。

EXSLT関数またはxsl:for-each「ループ」を実際に終了する方法がある場合(関数に戻り変数を割り当てることはできますが、関数は続行されます。for-eachは実際にはループではありませんが、関数に似ています。マップ)、それは理想的ですが、私はまだ方法を見つけていません。

すべてのフィードを1つの変数に結合し、for-eachループを完全に削除することを検討しましたが、これを最初から機能させるのに問題がありました。

他の可能な解決策、アイデア、またはポインタは大歓迎です!ここでのファイルの関係とXMLを変更するのはかなり難しいため、そのような変更を提案するソリューションは理想的ではありません。

よろしくお願いします、
トリスタンイーストバーン

4

2 に答える 2

0

ループを強制的に終了することはできないため、完全なリストを作成してから、最初の要素のみを返す必要があります。

<func:function name="cozi:findPost">
    <xsl:param name="post-url"/>  

    <xsl:variable name="blog-feeds" select="document('rss-feed-names.xml')/feeds"/>  

     <xsl:variable name="feedList">
         <xsl:for-each select="$blog-feeds/feed">
            <xsl:variable name="feed-file" select="document(@name)/atom:feed"/>
            <xsl:variable name="feed-entry" select="$feed-file/atom:entry[atom:link[contains(@href, $post-url)]]"/>
            <xsl:if test="$feed-entry">
                <xsl:value-of select="$feed-entry"/>
            </xsl:if>
        </xsl:for-each>
    </xsl:variable>
    <func:result select="$feedList[1]"/>
</func:function>

空のリスト条件の処理は演習として残されています :-)

于 2009-12-04T03:37:07.540 に答える
0

一般的な回答 (ジムの回答と同様) は、<func:result> を <xsl:for-each> 内に配置しないことです。この場合のより具体的な解決策では、<xsl:for-each> や <xsl:variable> を使用する必要はありません。XPath のみを使用できます。

<func:result select="(document
                       (document('rss-feed-names.xml')/feeds/@name)
                       /atom:feed
                       /atom:entry
                             [atom:link
                                   [contains(@href, $post-url)]]
                     )[1]"/>

これは、document() がノード セットを使用できるため機能します。実行されると、引数の各ノードによって参照されるドキュメントを取得します。複数入力/複数出力。

とはいえ、説明変数を賢明に使用すると、読みやすくなります。それでも、<xsl:for-each> を使用する必要はありません。

于 2009-12-07T22:32:31.967 に答える