2012-01-30 4 views
4

UmbracoのXSLTマクロを使用してXMLフィードを読み込み、コンテンツをうまく表示するようにしています。私のマクロはフィードが利用可能なときにうまく動作しますが、フィードが404を返すと、XSLTが正常に処理できるように管理できません。Umbraco XSLTマクロで不足しているXMLフィードを適切に処理します

umbraco.library:GetXmlDocumentByUrl()を使用してXMLを取得しています。 解析エラーが発生していることがわかりました。指定したエラーテキストを返す代わりにサイトがクラッシュすることがあります。

また、私は、エラーを少し良く処理するために使用できるかどうかを確認するために、document()テストでGetXmlDocumentByUrl()をラップしようとしました。私はこれがサイトがクラッシュするのを止め、XMLフィードが存在する場合は機能しますが、エラー・テキストを表示するのではなく解析エラーを作成することが判明しました。

私は私のコードは以下の通りです、この上の任意のヘルプやアドバイスをいただければと思います:

<xsl:variable name="feed" select="'http://url.to.feed'"/> 

<xsl:template match="/"> 
    <xsl:value-of select="document($feed)"/> 
    <!-- start writing XSLT --> 
    <xsl:choose> 
    <xsl:when test="string-length($feed) > 0 and $feed != ''"> 
     <xsl:choose> 
     <xsl:when test="document($feed)"> 
      File found 
      <xsl:variable name="feedContent" select="umbraco.library:GetXmlDocumentByUrl($feed, $cacheRate)"/> 
      <xsl:choose> 
      <xsl:when test="count($feedContent/error) &gt; 0"> 
      <!--<xsl:when test="$feedContent != 'error'">--> 
       <p class="feedList"> 
       <strong>This dynamic content is currently not available</strong><br /> 
       The content could not be loaded. Please verify that you are on the correct page and that you have an 
       active internet connection. 
       </p> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:call-template name="renderFeed"> 
       <xsl:with-param name="feedContent" select="$feedContent"/> 
       </xsl:call-template> 
      </xsl:otherwise> 
      </xsl:choose> 
     </xsl:when> 
     <xsl:otherwise> 
      Can't find the file... 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:when> 
    <xsl:otherwise> 
     <p class="feedList"> 
     <strong>No content exists for this page</strong><br /> 
     Please view another page. 
     </p> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

アップデート:私は次のように問題を単純化するために私のコードをダウンスキミング試してみた は、これをすることになっています私はそれが私たstatmentsを選択していないことを確認するためにすぐに値を私はそこに問題がないことを保証し、また、出力となるようGetXmlDocumentByUrlの非キャッシュ実装を使用します。

<xsl:template match="/"> 
    <!-- start writing XSLT --> 
    <xsl:choose> 
    <xsl:when test="string-length($feed) > 0 and $feed != ''"> 
     <xsl:variable name="vDoc" select="umbraco.library:GetXmlDocumentByUrl($feed)"/> 
     <xsl:value-of select="$vDoc"/> 
     <xsl:choose> 
     <xsl:when test="$vDoc"> 
      File found 
     </xsl:when> 
     <xsl:otherwise> 
      Can't find the file... 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:when> 
    <xsl:otherwise> 
     <p class="feedList"> 
     <strong>No content exists for this page</strong><br /> 
     Please view another page. 
     </p> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

明確404ページで、それは"System.Net"の文字列を返します。 WebException:リモートサーバーがエラーを返しました:(404)が見つかりません。 "System.Net.HttpWebRequest.GetResponse()at umbraco.library.GetXmlDocumentByUrl(String Url)"しかし、実際にタイムアウトに問題が発生しているフィードでは、私はfiddlerでダブルチェックして、ページが実際には200を返すではなく、XML文書が、私は次のように私のrenderFeedテンプレートであることを言及する必要がありますので、私はまだそれがむしろタイムアウト以外の方法でコンテンツを表示するために期待しているだろう。

<xsl:template name="renderFeed"> 
    <xsl:param name="feedContent" /> 
    <xsl:choose> 
    <xsl:when test="count($feedContent//item) &gt; 0"> 
     //Render Feed content 
    </xsl:when> 
    <xsl:otherwise> 
    <p class="feedList"> 
     <strong>No content exists for this page</strong><br /> 
     Please view another page. 
     </p> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

私は時にテストを得ましたたとえば、これをテストするより良い方法がありますか?

+0

404エラーが返されたときにGetXmlDocumentByUrl()によって返されたXMLサンプルを提供してください。 XPATH式(count($ feedContent/error)> 0)が誤って出力されている可能性があります。 – user47900

答えて

0

唯一の問題はあります。あなたはWebRequestタイムアウトプラスを変更できるように、私はUmbracoの元のものに基づいた簡単な関数を書いて、ContentTypeをチェックします。

public static XPathNodeIterator GetXmlDocumentByUrl(string Url, int requestTimeout = 100000) 
{ 
    XmlDocument xmlDoc = new XmlDocument(); 
    WebRequest request = WebRequest.Create(Url); 

    try 
    { 
     // Set the Request Timeout 
     request.Timeout = requestTimeout; 
     using (WebResponse response = request.GetResponse()) 
     { 
      if (response.ContentType.Contains("text/xml")) 
      { 
       using (Stream responseStream = response.GetResponseStream()) 
       { 
        XmlTextReader reader = new XmlTextReader(responseStream); 
        xmlDoc.Load(reader); 
       } 
      } 
      else 
       xmlDoc.LoadXml(string.Format("<error url=\"{0}\">Failed to load an ContentType of XML</error>", 
              HttpContext.Current.Server.HtmlEncode(Url))); 
     } 
    } 
    catch (WebException err) 
    { 
     xmlDoc.LoadXml(string.Format("<error url=\"{0}\">{1}</error>", 
            HttpContext.Current.Server.HtmlEncode(Url), err)); 
    } 
    catch (Exception err) 
    { 
     xmlDoc.LoadXml(string.Format("<error url=\"{0}\">{1}</error>", 
            HttpContext.Current.Server.HtmlEncode(Url), err)); 
    } 

    XPathNavigator xp = xmlDoc.CreateNavigator(); 
    return xp.Select("/"); 
} 
+0

この機能を使用していただきありがとうございます。問題を解決しました。 – marble

0

ここでは、document()関数の場合のW3C XSLT 1.0仕様の記述ですこれは、使用される特定のXSLTプロセッサが例外をスローしますが、静かに空のノードセットを返していない可能性があることをメンズ

"If there is an error retrieving the resource, then the XSLT processor may signal an error; if it does not signal an error, it must recover by returning an empty node-set"

:文書を取得したり、解析することはできません。

はこれを試してください - あなたは幸運である可能性があります

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:variable name="feed" select="'http://Some.Url.com'"/> 

    <xsl:template match="/"> 
     <xsl:variable name="vDoc" select="document($feed)"/> 

     <xsl:choose> 
      <xsl:when test="$vDoc"> 
       <!--Normal processing here --> 
      </xsl:when> 
      <xsl:otherwise> 
       <p class="feedList"> 
        <strong>No content exists for this page</strong> 
        <br />   Please view another page.  
       </p> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet> 

私は(使用しない)任意のXML文書に対してサクソンと、この変換を実行すると、約1分後、私はを得る:

あなたの XmlDocumenttext/htmlではなく text/xmlContentTypeをロードしている場合、私は見ることができます
<p class="feedList"> 
    <strong>No content exists for this page</strong> 
    <br/>   Please view another page.  
</p> 
+0

この提案をありがとう、私はそれを試み、UmbracoDebugTraceを表示している解析XSLTエラーがまだあります: ドキュメント 'http://url.to.feed'を読み込んでいるときにエラーが発生しました。エラーの詳細については、InnerExceptionを参照してください。 リモートサーバーからエラーが返されました。(404)が見つかりません。 at System.Net.HttpWebRequest.GetResponse() – marble

+0

@marble:これは、XSLTプロセッサが実際に例外をスローし、変換が異常終了することを意味します。 XSLTからrxceptionを捕まえて処理することはできません。これは、XSLT変換を呼び出すプログラムで行うことができます。 –

+0

そのように見えますが、UmbracoがGetXmlDocumentByUrlメソッドまたは同様のメソッドに組み込まれたソリューションを使用して、例外が正常に処理されたことを確認したいと考えていました。私たちは現在、Umbracoが提供するものを使用するのではなく、別の方法を書いて解決策を見つけようとしていますが、これを達成するためのより良い練習方法があればそれを愛しています。 – marble