Sample code for 30+ languages & platforms
Xbase++

XML Path Performance Optimizations

See more XML Examples

Discusses some important things to know about using Chilkat paths in the Chilkat XML API.

Chilkat Xbase++ Downloads

Xbase++
LOCAL nSuccess
LOCAL oXml
LOCAL nLicCount
LOCAL s
LOCAL i

nSuccess := 0

oXml := CreateObject("Chilkat.Xml")

//  Let's load XML containing the following:

//  <?xml version="1.0" encoding="utf-8"?>
//  <xyz>
//      <licenses>
//          <license>
//              <id>1234</id>
//          </license>
//          <license>
//              <id>1234</id>
//          </license>
//  ...
//  My sample XML contains 64,000 "license" nodes ..
//  ...
//          <license>
//              <id>1234</id>
//          </license>
//          <license>
//              <id>1234</id>
//          </license>
//      </licenses>
//  </xyz>
//  
nSuccess := oXml:LoadXmlFile("qa_output/large.xml")
IF (nSuccess != 1)
    ? oXml:LastErrorText
    oXml:destroy()
    RETURN
ENDIF

//  Iterating over the individual "license" nodes with this code snippet is
//  extremely slow:
nLicCount := oXml:NumChildrenHavingTag("licenses|license")
? "license count = " + Str(nLicCount)

i := 0
//  If "10" is changed to licCount, then it becomes apparent that this loop gets slower with each iteration.
DO WHILE i < 10
    oXml:I := i
    s := oXml:GetChildContent("licenses|license[i]|id")
    ? Str(i) + ": " + s
    i := i + 1
ENDDO

//  The reason it is extremely slow is that the "license[i]" part of the path passed to GetChildContent
//  says: find the i'th child of "licenses" having the tag "license".  Chilkat cannot assume that all
//  children of an XML node have the same tag.  Therefore it's not possible to directly access the i'th child.
//  Internally, Chilkat must start at the 1st child and iterate until it reaches the i'th child having the
//  tag "license".

//  For example, imagine if the XML was like this:

//  <?xml version="1.0" encoding="utf-8"?>
//  <xyz>
//      <licenses>
//          <license>
//              <id>1234</id>
//          </license>
//          <somethingElse>
//              <a>abc</a>
//          </somethingElse>
//          <license>
//              <id>1234</id>
//          </license>
//  ...

//  In the above XML, the 1st "license" is the 1st child of "licenses", but the 2nd "license"
//  is the 3rd child of "licenses".

//  If you already know that all children have the same tag, there is a shortcut that allows
//  for direct access to that child.  Just leave off the tag name, like this:

i := 0
//  If "10" is changed to licCount, then we can see the time for each loop is the same, and it's fast.
DO WHILE i < 10
    oXml:I := i
    s := oXml:GetChildContent("licenses|[i]|id")
    ? Str(i) + ": " + s
    i := i + 1
ENDDO

//  When we pass just the index "[i]", we're saying: Get the i'th child regardless of tag.
//  This is extremely fast because internally we can just access the i'th child directly.

//  Another performance improvement is to call NumChildrenAt rather than NumChildrenHavingTag.
//  For example:
nLicCount := oXml:NumChildrenAt("licenses")
? "licCount = " + Str(nLicCount)

//  NumChildrenAt returns the total number of children at the tag path.  If we already know
//  all children will have the same tag, we can just get the count.

oXml:destroy()