在Umbraco XSLT宏中优雅地处理缺少的XML源

在Umbraco XSLT宏中优雅地处理缺少的XML源

问题描述:

我正尝试在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

我能看到的唯一的问题是,如果你的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

这是什么的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