Gracefully handle missing XML feed in Umbraco XSLT Macro

I am trying to read an XML feed using an XSLT macro in Umbraco and display it in a good format. My macro works fine when the feed is available, but if the feed returns 404, I cannot get XSLT to gracefully handle it.

I get XML using umbraco.library: GetXmlDocumentByUrl () I found that it generates a parsing error, and sometimes it just crashes the site, and does not return the error text that I specified.

I also tried wrapping GetXmlDocumentByUrl () in the document () test to see if I can use this to fix the error a little better. I found that while this stops the site from crashes and works if an XML feed exists, it still generates a parsing error, rather than outputting my error text.

I would be grateful for any help or advice on this, my code is below:

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

Update: I tried to hide my code to simplify this problem to the following: it is supposed to use the implementation without caching GetXmlDocumentByUrl, so that I can make sure that I have no problem, and immediately print the value, make sure that these are not my selected entries:

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

With a specific 404 page, the string "System.Net.WebException is returned: the remote server returned an error: (404) Not found. In System.Net.HttpWebRequest.GetResponse () in umbraco.library.GetXmlDocumentByUrl (String Url)" However, with a feed that I actually get it with its timeout, I checked it twice with a violinist, and it seems that the page actually returns 200, but not an XML document, I should mention that in my renderFeed the template looks like this, so I would still expecting it to display content, not a timeout.

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

I got tests using an example, is there a better way I should test for this?

+4
source share
2 answers

The only problem I see is if your XmlDocument loads the ContentType from text/html and not text/xml . I wrote a simple function based on the original in Umbraco so that you can change the timeout of WebRequest plus, it checks the 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
source

This is what the W3C XSLT 1.0 specification says when the document() function cannot retrieve or parse a document

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

This means that the particular XSLT processor used does not throw an exception, but silently returns an empty node-set.

Just try this - you might be lucky :

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

When I run this conversion with Saxon against any XML document (not used), after about 1 minute I get :

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

Source: https://habr.com/ru/post/1393821/


All Articles