Thanks for the help. Using the reader has helped a little bit in the
performance, but I am still taking a big hit when I load the data into my
collection. If I write the output directly to the console it takes a split
second to write 24 appointments. As soon as I load the XML into the
collection and then loop through the collection to display an appointment,
the time jumps up to over 5 seconds.
The main reason I load the data into the collection is so I can loop through
the collection in the dayrender of the calendar control. Is there a better
way to get from the XML string to populating the calendar control that I am
missing?
Thanks,
Kurt Bauer
Here is my new code using the XML reader:
Dim oAppointment As Calendar.Appointment
Dim oAppointments As Calendar.Appointments
Dim doc As Xml.XPath.XPathDocument = New Xml.XPath.XPathDocument(New
XmlTextReader(New System.IO.StringReader(strXML)))
Dim nav As Xml.XPath.XPathNavigator = doc.CreateNavigator()
Dim oNSManager As XmlNamespaceManager = New
XmlNamespaceManager(nav.NameTable)
Dim expression As Xml.XPath.XPathExpression = nav.Compile("//a:prop")
oNSManager.AddNamespace("a", "DAV:")
expression.SetContext(oNSManager)
Dim it As Xml.XPath.XPathNodeIterator = nav.Select(expression)
If it.Count > 0 Then
oAppointments = New Calendar.Appointments
' Walk the response collection
While it.MoveNext
oAppointment = New Calendar.Appointment
Dim appointments As Xml.XPath.XPathNavigator = it.Current
Dim children As Xml.XPath.XPathNodeIterator =
appointments.SelectChildren(XPath.XPathNodeType.El ement)
While children.MoveNext
Select Case children.Current.LocalName
Case "subject"
Dim intIndex As Integer
intIndex = InStr(1, children.Current.Value, ":")
If intIndex > 0 Then
oAppointment.Category = Mid(children.Current.Value, 1,
intIndex - 1)
oAppointment.Subject = Mid(children.Current.Value,
intIndex + 1)
Else
oAppointment.Subject = children.Current.Value
End If
intIndex = Nothing
Case "dtstart"
oAppointment.StartTime = children.Current.Value
Case "dtend"
oAppointment.EndTime = children.Current.Value
Case "location"
oAppointment.Location = children.Current.Value
Case "alldayevent"
oAppointment.AllDayEvent = children.Current.Value
Case "reminderoffset"
oAppointment.ReminderOffset = children.Current.Value / 60
Case "description"
oAppointment.Body = children.Current.Value
End Select
End While
oAppointments.Add(oAppointment)
oAppointment = Nothing
End While
End If
Here are my 2 collections for reference:
Public Class Appointments
Implements IEnumerable
Private mcolItems As Collection
Public Sub New()
mcolItems = New Collection
End Sub
Public ReadOnly Property Count()
Get
Count = mcolItems.Count
End Get
End Property
Sub Add(ByVal objNew As Calendar.Appointment)
mcolItems.Add(objNew)
End Sub
Public ReadOnly Property Item(ByVal vIndex As Object) As Appointment
Get
Item = mcolItems.Item(vIndex)
End Get
End Property
End Class
Public Class Appointment
Private strUrl As String
Private dtStartTime As DateTime
Private dtEndTime As DateTime
Private strSubject As String
Private strLocation As String
Private strBody As String
Private strCategory As String
Private strBusyStatus As String
Private blnAllDayEvent As Boolean
Private lngReminderOffset As Long
Private objAttendies As Calendar.Attendies
Public Property EmailUrl() As String
Get
Return strUrl
End Get
Set(ByVal Value As String)
strUrl = Value
End Set
End Property
Public Property StartTime() As DateTime
Get
Return dtStartTime
End Get
Set(ByVal Value As DateTime)
dtStartTime = Value
End Set
End Property
Public Property EndTime() As DateTime
Get
Return dtEndTime
End Get
Set(ByVal Value As DateTime)
dtEndTime = Value
End Set
End Property
Public Property Subject() As String
Get
Return strSubject
End Get
Set(ByVal Value As String)
strSubject = Value
End Set
End Property
Public Property Location() As String
Get
Return strLocation
End Get
Set(ByVal Value As String)
strLocation = Value
End Set
End Property
Public Property Body() As String
Get
Return strBody
End Get
Set(ByVal Value As String)
strBody = Value
End Set
End Property
Public Property Category() As String
Get
Return strCategory
End Get
Set(ByVal Value As String)
strCategory = Value
End Set
End Property
Public Property BusyStatus() As String
Get
Return strBusyStatus
End Get
Set(ByVal Value As String)
strBusyStatus = Value
End Set
End Property
Public Property AllDayEvent() As Boolean
Get
Return blnAllDayEvent
End Get
Set(ByVal Value As Boolean)
blnAllDayEvent = Value
End Set
End Property
Public Property ReminderOffset() As Long
Get
Return lngReminderOffset
End Get
Set(ByVal Value As Long)
lngReminderOffset = Value
End Set
End Property
Public Property Attendies() As Calendar.Attendies
Get
Return objAttendies
End Get
Set(ByVal Value As Calendar.Attendies)
objAttendies = Value
End Set
End Property
Sub New()
objAttendies = Calendar.Attendies.GetAttendies
End Sub
End Class
"Christoph Schittko [MVP]" <ch********************@austin.rr.com> wrote in
message news:ue**************@TK2MSFTNGP10.phx.gbl...
Kurt,
try the XPathNavigator/XPathNodeIterator combo rather than the
XmlDocument. This combo is optimized for read-only XPath access and performs better
than the SelectNodes couterpart.
See the code snippet below. I hope you get the idea:
Dim doc As Xml.XPath.XPathDocument = New Xml.XPath.XPathDocument(New
XmlTextReader(New System.IO.StringReader(strXML)))
Dim nav As Xml.XPath.XPathNavigator = doc.CreateNavigator()
Dim oNSManager As XmlNamespaceManager = New
XmlNamespaceManager(nav.NameTable)
Dim expression As Xml.XPath.XPathExpression = nav.Compile("//a:prop")
oNSManager.AddNamespace("a", "DAV:")
expression.SetContext(oNSManager)
Dim it As Xml.XPath.XPathNodeIterator = nav.Select(expression)
' Walk the response collection
While it.MoveNext
Dim appointments As Xml.XPath.XPathNavigator = it.Current
Dim children As Xml.XPath.XPathNodeIterator =
appointments.SelectChildren(XPath.XPathNodeType.El ement)
While children.MoveNext
Select Case children.Current.LocalName
Case "subject"
Dim intIndex As Integer
intIndex = InStr(1, children.Current.Value, ":")
If intIndex > 0 Then
Console.WriteLine(String.Format("Category {0}",
Mid(children.Current.Value, 1, intIndex - 1)))
Console.WriteLine(String.Format("subject {0}",
Mid(children.Current.Value, intIndex + 1)))
Else
children.Current.MoveToFirstChild()
Console.WriteLine(String.Format("subject {0}",
children.Current.Value))
End If
' ...
HTH,
Christoph Schittko
Software Architect, .NET Mentor
MS MVP XML .NET
"Kurt Bauer" <kb****@NOSPAMtampabay.rr.com> wrote in message
news:uK**************@TK2MSFTNGP09.phx.gbl... I'm pretty new to .net development, so I used an msdn article to give me
some guidance on getting the xml from Exchange. Here is a link.
http://msdn.microsoft.com/library/de...asp?frame=true Here is my function to parse my xml string.
Private Shared Function ConvertXMLtoAppointment(ByVal strXML As
String) As Calendar.Appointments
' this routine takes the XML stream and puts it into a
collection of appointments
Dim oAppointment As Calendar.Appointment
Dim oAppointments As Calendar.Appointments
Dim oXML As New Xml.XmlDocument
oXML.LoadXml(strXML)
Dim oNSManager As XmlNamespaceManager = New
XmlNamespaceManager(oXML.NameTable)
oNSManager.AddNamespace("a", "DAV:")
Dim oResponses As Xml.XmlNodeList =
oXML.SelectNodes("//a:prop", oNSManager)
oXML = Nothing
oNSManager = Nothing
Dim iResponseLoop As Int16
Dim iLoop As Int16
' Walk the response collection
If oResponses.Count > 0 Then
Try
'load collection
oAppointments = New Calendar.Appointments
'loop through each response
For iResponseLoop = 0 To oResponses.Count - 1
'load appointment into collection
Dim oNode As Xml.XmlNode
oNode = oResponses.Item(iResponseLoop)
oAppointment = New Calendar.Appointment
For iLoop = 0 To oNode.ChildNodes.Count - 1
Select Case
oNode.ChildNodes.Item(iLoop).Name Case "subject"
Dim intIndex As Integer
intIndex = InStr(1,
oNode.ChildNodes.Item(iLoop).InnerText, ":")
If intIndex > 0 Then
oAppointment.Category =
Mid(oNode.ChildNodes.Item(iLoop).InnerText, 1, intIndex - 1)
oAppointment.Subject =
Mid(oNode.ChildNodes.Item(iLoop).InnerText, intIndex + 1)
Else
oAppointment.Subject =
oNode.ChildNodes.Item(iLoop).InnerText
End If
intIndex = Nothing
Select Case oAppointment.Category
Case "Conference Call"
Case "Events"
Case "Meeting"
Case "Other"
Case "Personal"
Case "Vacation"
Case Else
oAppointment.Category = ""
oAppointment.Subject =
oNode.ChildNodes.Item(iLoop).InnerText
End Select
Case "dtstart"
oAppointment.StartTime =
oNode.ChildNodes.Item(iLoop).InnerText
Case "dtend"
oAppointment.EndTime =
oNode.ChildNodes.Item(iLoop).InnerText
Case "location"
oAppointment.Location =
oNode.ChildNodes.Item(iLoop).InnerText
Case "alldayevent"
oAppointment.AllDayEvent =
oNode.ChildNodes.Item(iLoop).InnerText
Case "reminderoffset"
oAppointment.ReminderOffset =
oNode.ChildNodes.Item(iLoop).InnerText / 60
Case "description"
oAppointment.Body =
oNode.ChildNodes.Item(iLoop).InnerText
End Select
Next
oAppointments.Add(oAppointment)
oAppointment = Nothing
Next
Catch ex As Exception
oAppointment = Nothing
Finally
iLoop = Nothing
iResponseLoop = Nothing
End Try
End If
oResponses = Nothing
ConvertXMLtoAppointment = oAppointments
oAppointments = Nothing
oAppointment = Nothing
End Function
Here is a small sample of an xml string I am trying to parse into my
collection.
<?xml version="1.0"?><a:multistatus
xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" xmlns:c="xml:"
xmlns:d="urn:schemas-microsoft-com:office:office"
xmlns:a="DAV:"><a:response><a:href>http://localhost/exchange/kurtbauer/Calen
dar/{D1A44985-AD7A-41E9-97BA-A6245517AB4C}.EML</a:href><a:propstat><a:statusHTTP/1.1 200
OK</a:status><a:prop><url>http://localhost/exchange/kurtbauer/Calendar/{D1A4 4985-AD7A-41E9-97BA-A6245517AB4C}.EML</url><subject>Conference Call:Add
my initials KB</subject><dtstart
b:dt="dateTime.tz">2003-07-15T21:00:00.000Z</dtstart><dtend
b:dt="dateTime.tz">2003-07-15T22:00:00.000Z</dtend></a:prop></a:propstat></a
:response><a:response><a:href>http://localhost/exchange/kurtbauer/Calendar/{
FF5A919B-0FB0-4AF0-8013-42F4CC5F3B4D}.EML</a:href><a:propstat><a:status>HTTP /1.1 200
OK</a:status><a:prop><url>http://localhost/exchange/kurtbauer/Calendar/{FF5A 919B-0FB0-4AF0-8013-42F4CC5F3B4D}.EML</url><subject>Vacation:I need a
vacation (KB)</subject><dtstart
b:dt="dateTime.tz">2003-07-27T04:00:00.000Z</dtstart><dtend
b:dt="dateTime.tz">2003-07-28T04:00:00.000Z</dtend></a:prop></a:propstat></a :response></a:multistatus>
Thanks,
Kurt Bauer
"Christoph Schittko [MVP]" <ch********************@austin.rr.com> wrote
in message news:O6**************@tk2msftngp13.phx.gbl... Kurt,
How are you loading the Xml data into the collection? If you could
post code or proovide some details I could probably provide some details. There may be faster ways to do it. Does populating the collection involve executing
a lot of XPath expressions? Then make sure you are using an XPathDocument.
Is it simple, forward-only parsing of the XML, then you should try using an
XmlReader or XmlSerialization (which is built around XmlReaders).
HTH,
Christoph Schittko
Software Architect, .NET Mentor
MVP XML .NET
"Kurt Bauer" <kb****@NOSPAMtampabay.rr.com> wrote in message
news:e8**************@TK2MSFTNGP12.phx.gbl...
> I have an ASP group calendar application which pulls calendar data from > Exchange via webdav into an XML string. I then loop the XML nodes
to > populate a collection of appointments. Finally I use the
appointment > collection to populate the calendar control. The performance
getting the > XML data is fine, but loading the data into the collection is slow.
My > question/problem is should I be using the collection, a dataset, or
> something else to load the xml data into the calendar control?
> Thanks,
> Kurt Bauer
>
>