2012-01-30 262 views
4

我正嘗試在Umbraco中使用XSLT宏讀取XML源,並讓它顯示格式良好的內容。當Feed可用時,My Macro可以正常工作,但如果Feed返回404,我無法設法讓XSLT正常處理它。我發現它創建了一個解析錯誤,有時它只是崩潰的網站,而不是返回我指定的錯誤文本。我發現它正在創建一個解析錯誤,有時它只是崩潰的網站,而不是返回我指定的錯誤文本。在Umbraco XSLT宏中優雅地處理缺少的XML源

我也嘗試在文檔()測試中包裝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> 

更新: 我試過撇了我的代碼,以簡化的問題以下,這應該使用GetXmlDocumentByUrl的非緩存實現,這樣我會確保我沒有問題存在,也輸出直線距離的值,以確保它不是我的選擇statments:

<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()在umbraco.library.GetXmlDocumentByUrl(字符串Url)「然而,飼料,我實際上有問題,它的超時,我仔細檢查與小提琴手,似乎該網頁實際上返回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 2012-01-30 18:28:10

回答

0

我能看到的唯一的問題是,如果你的XmlDocument加載的text/html而非text/xml一個ContentType。我寫了一個簡單的函數,基於Umbraco中的原始函數,以允許您更改WebRequest超時加,它會檢查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 2012-02-03 18:38:25

0

這是什麼的W3C XSLT 1.0規範說的情況下,document()函數無法檢索或解析文檔

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

該男子有特定的XSLT處理器使用不拋出異常的機會,只是默默地返回一個空節點集。

剛剛嘗試這一點 - 你可能會幸運

<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分鐘後,我得到

<p class="feedList"> 
    <strong>No content exists for this page</strong> 
    <br/>   Please view another page.  
</p> 
+0

Thankyou對於這個建議,我試了一下,仍然得到了解析UmbracoDebugTrace的XSLT錯誤: 加載文檔'http://url.to.feed'時發生錯誤。有關錯誤的完整說明,請參閱InnerException。 遠程服務器返回錯誤:(404)未找到。 at System.Net.HttpWebRequest.GetResponse() – marble 2012-01-31 09:59:20

+0

@marble:那麼這意味着你的XSLT處理器真的會拋出一個異常,這會中止轉換。您無法捕捉並處理來自XSLT的視覺。您可以在調用XSLT轉換的程序中這樣做。 – 2012-01-31 12:48:52

+0

看起來確實如此,我希望Umbraco可以在GetXmlDocumentByUrl方法或類似方法中內置一個解決方案,以確保異常處理得當。我們目前正在努力通過編寫一個單獨的方法來尋找解決方案,而不是使用Umbraco提供的任何方法,但是如果有更好的實踐方法來實現這一點,它會很喜歡它。 – marble 2012-01-31 13:07:37