Изящно обрабатывать недостающий XML-канал в Umbraco XSLT Macro - PullRequest
4 голосов
/ 30 января 2012

Я пытаюсь читать в XML-канале с помощью макроса XSLT в Umbraco, чтобы он отображал содержимое в хорошем формате. Мой макрос работает нормально, когда канал доступен, но если он возвращает 404, мне не удается заставить XSLT изящно с ним справиться.

Я получаю XML с помощью umbraco.library: GetXmlDocumentByUrl () Я обнаружил, что он создает ошибку синтаксического анализа и что иногда он просто приводит к сбою сайта, а не возвращает указанный мной текст ошибки.

Я также попытался обернуть GetXmlDocumentByUrl () в тесте document (), чтобы посмотреть, смогу ли я использовать это, чтобы немного лучше обработать ошибку. Я обнаружил, что хотя это останавливает сайт от сбоев и работает, если 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, чтобы я мог убедиться, что у меня нет проблем, а также вывел бы значение сразу убедитесь, что это не мой выбор оценок:

 <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) Not Found. At System.Net.HttpWebRequest.GetResponse () в 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>

Я получил тесты на примере, есть ли лучший способ, которым я должен проверять это?

Ответы [ 2 ]

0 голосов
/ 31 января 2012

Единственная проблема, которую я вижу, это если ваш XmlDocument загружает ContentType из text/html вместо text/xml.Я написал простую функцию, основанную на оригинальной Umbraco, чтобы позволить вам изменить WebRequest timeout plus, он проверяет 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 голосов
/ 31 января 2012

Вот что сказано в спецификации W3C XSLT 1.0 для случая, когда функция document() не может получить или проанализировать документ :

" Если при извлечении ресурса произошла ошибка, XSLT процессор может сигнализировать об ошибке; если он не сигнализирует об ошибке, он должен восстановить, вернув пустой набор узлов"

Это означает, что существует вероятность того, что конкретный используемый процессор 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>

Когда я запускаю это преобразование с Saxon для любого XML-документа (не используется), примерно через 1 минуту я получаю :

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