Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Drew 165 posts 340 karma points
    Aug 04, 2011 @ 16:27
    Drew
    0

    Parsing XML from local document

    I've spent a couple of hours faffing with this and I've had a root around the forum but I must be missing something obvious.

    I had a macro that called an external URL for an API, got back some XML and iterated through the results.
    (well, I actually called a custom extension which called the URL for me and returned XML)


    Example:

     

         <xsl:variable name="EventXml" select="Eventbrite.User:User_ListEvents($ebAppKey, $ebUserKey, '', '', $eventStatuses, '')" />
         <xsl:for-each select="ucomponents.xml:Parse($EventXml)//events/event">
    .... stuff here ..

         </xsl:for-each>


    Example of XML returned (simplified):

     

    <?xml version="1.0" encoding="UTF-8" ?>
    <events>
    <event>
    <id>1768877761</id>
                     <start_date>2011-08-03 13:00:00</start_date>
            </event>
    <event>
    <id>1234</id>
                     <start_date>2010-09-01 11:00:00</start_date>
            </event>
    </events>

     

     

     

    All was fine, until I realised high traffic site = many API calls.
    So FeedCache2 to the rescue. Great. :)

    Now the XML is in a file stored locally (App_Data/FeedCache/myfilename.xml).
    My macro can load the XML. Then filter the events by their 'start date' - so I can display events past, future or all events.

    The problem?

    If I "count" the number of event nodes, it works and I get '2' back. Great!
    But when I try to foreach iterate through them using the same syntax, it fails.

        <!-- File location -->
        <xsl:variable name="fileLocation" select="'C:\inetpub\wwwroot\App_Data\FeedCache\AllEvents2.xml'"/>
         <!-- Get cached data -->
        <xsl:variable name="FileXml" select="umbraco.library:GetXmlDocument($fileLocation, 'false')" />
      
        <!-- Get the correct nodes based on if we're only meant to be showing all, previous or future events -->
        <xsl:variable name="EventXml">
          <xsl:choose>
            <xsl:when test="/macro/showEvents != '' and /macro/showEvents = 'future'">
              <xsl:copy-of select="$FileXml//events [umbraco.library:DateGreaterThanOrEqualToday(event/start_date)]"/>
            </xsl:when>
            <xsl:when test="/macro/showEvents != '' and /macro/showEvents = 'past'">
              <xsl:copy-of select="$FileXml//events [umbraco.library:DateDiff(umbraco.library:CurrentDate(), event/start_date, 's') &gt; 0]"/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:copy-of select="$FileXml//events"/>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:variable>
         
      <xsl:value-of select="count(ucomponents.xml:Parse($EventXml)/*)"/>

    Filtering the events by date works fine and the content of $EventXml is correct.
    The 'count' statement above displays "2" - as there are two <event> nodes.

    But this next line fails:

    <xsl:for-each select="ucomponents.xml:Parse($EventXml)/*">


    Like so:

    Error parsing the XSLT:
    System.OverflowException: Value was either too large or too small for an Int32. at System.Convert.ToInt32(Double value) at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider) at System.Xml.Xsl.Runtime.XmlQueryRuntime.ChangeTypeXsltArgument(XmlQueryType xmlType, Object value, Type destinationType) at System.Xml.Xsl.Runtime.XmlQueryContext.InvokeXsltLateBoundFunction(String name, String namespaceUri, IList`1[] args) at (XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime, XPathNavigator {urn:schemas-microsoft-com:xslt-debug}current) at Root(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime) at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter writer) at System.Xml.Xsl.XslCompiledTransform.Transform(IXPathNavigable input, XsltArgumentList arguments, TextWriter results) at umbraco.macro.GetXsltTransformResult(XmlDocument macroXML, XslCompiledTransform xslt, Dictionary`2 parameters) at umbraco.presentation.umbraco.developer.Xslt.xsltVisualize.visualizeDo_Click(Object sender, EventArgs e)

     


    I've tried masses of syntaxes. I can only think that the foreach fails because there is no 'root' node in the results after I get the Events I want (by date).
    As the XML will look like this:

      <event>
    <id>1768877761</id>
                     <start_date>2011-08-03 13:00:00</start_date>
            </event>
    <event>
    <id>1234</id>
                     <start_date>2010-09-01 11:00:00</start_date>
            </event>

    Any suggestions greatly appreciated!
    (it's driving me mad)
     
  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 8x admin c-trib
    Aug 06, 2011 @ 14:13
    Chriztian Steinmeier
    2

    Hi Drew,

    You should use the node-set() extension function to convert the $EventXml variable back into an XPath-navigable variable, not the Parse() function (which just converts a string of XML into actual XML nodes):

    <xsl:for-each select="msxml:node-set($EventXml)">
    <!-- Do stuff with <event> nodes -->
    </xsl:for-each>

    Not sure about the error, though - usually that's due to a call to GetMedia() or NiceUrl() without an id...

    /Chriztian

  • Drew 165 posts 340 karma points
    Aug 24, 2011 @ 09:56
    Drew
    0

    Node-set works great.

    Also the error disappeared when I switched over the node-set, I can only assume that calling Parse meant that the XSLT parser assumed one of the values used could potentially be invalid/null.

     

    Cheers!

Please Sign in or register to post replies

Write your reply to:

Draft