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 339 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 2726 posts 8320 karma points MVP 4x 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 339 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!

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies