[bb] XML code by GrahamK [ 1+ years ago ]

Started by BlitzBot, June 29, 2017, 00:28:38

Previous topic - Next topic

BlitzBot

Title : XML code
Author : GrahamK
Posted : 1+ years ago

Description : Will add further comments/descriptions later

Code :
Code (blitzbasic) Select
; XML load / parse / save functions

Type sdXMLnodelist
Field node.sdxmlnode
Field nextnode.sdxmlnodelist
Field prevnode.sdxmlnodelist
End Type

; for internal use, do not use in code outside of this file
Type sdXMLworklist
Field node.sdxmlnode
End Type


Type sdXMLnode
Field tag$,value$,path$
Field firstattr.sdXMLattr
Field lastattr.sdXMLattr
Field attrcount,fileid
Field endtag$

; linkage functionality
Field firstchild.sdXMLnode
Field lastchild.sdXMLnode
Field childcount
Field nextnode.sdXMLnode
Field prevnode.sdXMLnode
Field parent.sdXMLnode
End Type

Type sdXMLattr
Field name$,value$
Field sibattr.sdXMLattr
Field parent.sdxmlnode
End Type

Global SDXMLFILEID

Function sdReadXML.sdXMLnode(filename$)
infile = ReadFile(filename$)
SDXMLFILEID=MilliSecs()
x.sdxmlnode = sdXMLReadNode(infile,Null)
CloseFile infile
Return x
End Function

Function sdWriteXML(filename$,node.sdxmlnode,writeroot=False)
outfile = WriteFile(filename$)
WriteLine outfile,"<?xml version="+Chr$(34)+"1.0"+Chr$(34)+" ?>"
sdXMLwriteNode(outfile,node)
CloseFile outfile
End Function



Function sdXMLOpenNode.sdxmlnode(parent.sdxmlnode,tag$="")
;gak debuglog "Opening new node"
x.sdxmlnode = New sdxmlnode
x ag$=tag$
xfileid = SDXMLFILEID; global indicator to group type entries (allows multiple XML files to be used)
sdXMLaddNode(parent,x)
Return x
End Function

Function sdXMLCloseNode.sdxmlnode(node.sdxmlnode)
;gak debuglog "Closing node ["+node ag$+"]"
If nodeparent <> Null Then
;gak debuglog "Returning to parent ["+nodeparent ag$+"]"
Else
;gak debuglog "No Parent found"
End If
Return nodeparent
End Function

; adds node to end of list (need separate function for insert, or mod this on)
Function sdXMLAddNode(parent.sdxmlnode,node.sdxmlnode)
If parent <> Null
;gak debuglog "Parent of node = ["+parent ag$+"]"
If parentchildcount = 0 Then
parentfirstchild = node
Else
parentlastchild
extnode = node
End If
nodeprevnode = parentlastchild
parentlastchild = node
parentchildcount = parentchildcount +1
nodepath$ = parentpath$+parent ag$
End If
nodeparent = parent
nodepath$=nodepath$+"/"
;gak debuglog "path to ["+node ag$+"]={"+nodepath$+"}"
End Function


Function sdXMLDeleteNode(node.sdxmlnode)
n.sdxmlnode = nodefirstchild
; delete any children recursively
While n <> Null
nn.sdxmlnode= n
extnode
sdXMLdeletenode(n)
n = nn
Wend

; delete attributes for this node
a.sdxmlattr = nodefirstattr
While a <> Null
na.sdxmlattr = asibattr
Delete a
a = na
Wend

; dec parents child count
If nodeparent <> Null
nodeparentchildcount = nodeparentchildcount -1

; heal linkages
If nodeprevnode <> Null Then nodeprevnode
extnode = node
extnode
If node
extnode <> Null Then node
extnodeprevnode = nodeprevnode
If nodeparentfirstchild = node Then nodeparentfirstchild = node
extnode
If nodeparentlastchild = node Then nodeparentlastchild = nodeprevnode
End If
; delete this node
; ;gak debuglog "DELETING:"+node ag$
Delete node

End Function


; node functions

Function sdXMLfindNode.sdXMLnode(node.sdxmlnode,path$)
;gak debuglog "------------- Perfoming Find ("+path$+")------------"

ret.sdXMLnode = Null
p=Instr(path$,"/")
If p > 0 Then
tag$=Left$(path$,p-1)
;gak debuglog "Looking for ["+tag$+"]"
a.sdxmlnode = node
While ret=Null And a<>Null
;gak debuglog "Checking...["+a ag$+"]"
If Lower(tag$)=Lower(a ag$) Then
If p=Len(path$) Then
;gak debuglog "Found..."
ret = a
Else
If afirstchild <> Null Then
ret = sdxmlfindnode(afirstchild,Mid$(path$,p+1))
End If
End If
End If
a = a
extnode
Wend
End If
Return ret
End Function

Function sdXMLDeleteList(nl.sdxmlnodelist)
While nl <> Null
na.sdxmlnodelist = nl
extnode
Delete nl
nl = na
Wend
End Function


Function sdXMLSelectNodes.sdxmlnodelist(node.sdxmlnode,path$,recurse=True)
root.sdxmlnodelist=Null
sdxmlselectnodesi(node,path$,recurse)
prev.sdxmlnodelist=Null
c = 0
For wl.sdxmlworklist = Each sdxmlworklist
c = c + 1
nl.sdxmlnodelist = New sdxmlnodelist
nl
ode = wl
ode
If prev = Null Then
root = nl
prev = nl
Else
prev
extnode = nl
nlprevnode = prev
End If
prev = nl
Delete wl
Next
;gak debuglog "XML: "+c+" nodes selected"
Return root
End Function

; internal selection function, do not use outside this file
Function sdXMLSelectNodesI(node.sdxmlnode,path$,recurse=True)
wl.sdXMLworklist=Null
;gak debuglog "------------- Perfoming Select ("+path$+")------------"
If node = Null Then
;gak debuglog "Search node is null!!!"
End If
ret.sdXMLnode = Null
p=Instr(path$,"/")
If p > 0 Then
tag$=Left$(path$,p-1)
a.sdxmlnode = node
While a<>Null
;gak debuglog "Looking for {"+path$+"} in {"+apath$+a ag$+"/}  {"+Lower(Right$(apath$+a ag$+"/",Len(path$)))+"} @"
If Lower(path$)=Lower(Right$(apath$+a ag$+"/",Len(path$))) Then
wl = New sdXMLworklist
wl
ode = a
;gak debuglog ">>FOUND"
End If
If afirstchild <> Null And (recurse) Then
sdXMLSelectNodesI(afirstchild,path$)
End If
a = a
extnode
Wend
End If

End Function

Function sdXMLNextNode.sdXMLnode(node.sdXMLnode)
Return node
extnode
End Function

Function sdXMLPrevNode.sdXMLnode(node.sdXMLnode)
Return nodeprevnode
End Function

Function sdXMLAddAttr(node.sdxmlnode,name$,value$)
;gak debuglog "XML:adding attribute "+name$+"="+value$+" ("+Len(value$)+")"
a.sdxmlattr = New sdxmlattr
a
ame$ = name$
avalue$ = value$
If nodeattrcount = 0 Then
nodefirstattr = a
Else
nodelastattrsibattr = a
End If
nodelastattr=a
nodeattrcount = nodeattrcount + 1
aparent = node
End Function


Function sdXMLReadNode.sdxmlnode(infile,parent.sdXMLnode,pushed=False)
mode = 0
root.sdxmlnode = Null
cnode.sdxmlnode = Null
x.sdXMLnode = Null
ispushed = False
done = False
While (Not done) And (Not Eof(infile))
c = ReadByte(infile)
If c<32 Then c=32
ch$=Chr$(c)
; ;gak debuglog "{"+ch$+"} "+c+" mode="+mode
Select mode
 Case 0 ; looking for the start of a tag, ignore everything else
If ch$ = "<" Then
mode = 1; start collecting the tag
End If
 Case 1 ; check first byte of tag, ? special tag
   If ch$ = "?" Or ch$ = "!" Then
mode = 0; class special nodes as garbage & consume
Else
If ch$ = "/" Then
mode = 2 ; move to collecting end tag
xendtag$=ch$
;gak debuglog "** found end tag"
Else
cnode=x
x.sdXMLnode = sdXMLOpennode(cnode)
If cnode=Null Then root=x
x ag$=ch$
mode = 3 ; move to collecting start tag
End If
End If
 Case 2 ; collect the tag name (close tag)
If ch$=">" Then
mode = 0 ; end of the close tag so jump out of loop
;done = True
x = sdXMLclosenode(x)
Else
xendtag$ = xendtag$ + ch$
End If
 Case 3 ; collect the tag name
If ch$=" " Then
;gak debuglog "TAG:"+x ag$
mode = 4 ; tag name collected, move to collecting attributes
Else
If ch$="/" Then
;gak debuglog "TAG:"+x ag$
xendtag$=x ag$
mode = 2; start/end tag combined, move to close
Else
If ch$=">" Then
;gak debuglog "TAG:"+x ag$
mode = 20; tag closed, move to collecting value
Else
x ag$ = x ag$ + ch$
End If
End If
End If
 Case 4 ; start to collect attributes
   If Lower(ch$)>="a" And Lower(ch$)<="z" Then
aname$=ch$;
   mode = 5; move to collect attribute name
Else
If ch$=">" Then
xvalue$=""
mode = 20; tag closed, move to collecting value
Else
If ch$="/" Then
mode = 2 ; move to collecting end tag
xendtag$=ch$
;gak debuglog "** found end tag"
End If
End If
End If
 Case 5 ; collect attribute name
   If ch$="=" Then
 ;gak debuglog "ATT:"+aname$
 aval$=""
 mode = 6; move to collect attribute value
Else
 aname$=aname$+ch$
End If
 Case 6 ; collect attribute value
   If c=34 Then
mode = 7; move to collect string value
Else
If c <= 32 Then
;gak debuglog "ATV:"+aname$+"="+aval$
sdXMLAddAttr(x,aname$,aval$)
mode = 4; start collecting a new attribute
Else
  aval$=aval$+ch$
End If
End If
 Case 7 ; collect string value
If c=34 Then
;gak debuglog "ATV:"+aname$+"="+aval$
sdxmlADDattr(x,aname$,aval$)
mode = 4; go and collect next attribute
Else
aval$=aval$+ch$
End If
 Case 20 ; COLLECT THE VALUE PORTION
If ch$="<" Then
;gak debuglog "VAL:"+x ag$+"="+xvalue$
mode=1; go to tag checking
Else
xvalue$=xvalue$+ch$
End If
End Select

If Eof(infile) Then done=True

Wend

Return root

End Function

; write out an XML node (and children)
Function sdXMLWriteNode(outfile,node.sdxmlnode,tab$="")
; ;gak debuglog "Writing...."+node ag$+".."
s$="<"+node ag$
a.sdxmlattr = nodefirstattr
While a<>Null
; ;gak debuglog "Writing attr ["+a
ame$+"]=["+avalue$+"]"
s$ = s$+" "+Lower(a
ame$)+"="+Chr$(34)+avalue$+Chr$(34)
a = asibattr
Wend

If nodevalue$="" And nodechildcount = 0 Then
s$=s$+"/>"
et$=""
Else
s$=s$+">"+nodevalue$
et$="</"+node ag$+">"
End If

WriteLine outfile,sdXMLcleanStr$(tab$+s$)
n.sdxmlnode = nodefirstchild
While n <> Null
sdXMLwriteNode(outfile,n,tab$+"  ")
n = n
extnode
Wend

If et$<> "" Then WriteLine outfile,sdXMLcleanStr$(tab$+et$)

End Function




; remove non-visible chars from the output stream
Function sdXMLCleanStr$(s$)
a$=""
For i = 1 To Len(s$)
If Asc(Mid$(s$,i,1))>=32 Then a$ = a$ +Mid$(s$,i,1)
Next
Return a$

End Function

; attribute functions
; return an attribute of a given name
Function sdXMLFindAttr.sdXMLattr(node.sdxmlnode,name$)
ret.sdXMLattr = Null
If node <> Null Then
a.sdxmlattr = nodefirstattr
done = False
While ret=Null And a<>Null
If Lower(name$)=Lower(a
ame$) Then
ret = a
End If
a = asibattr
Wend
End If
Return ret
End Function

; return an attribute value as a string
Function sdXMLAttrValueStr$(node.sdxmlnode,name$,dflt$="")
ret$=dflt$
a.sdxmlattr = sdXMLfindattr(node,name$)
If a <> Null Then ret$=avalue$
Return ret$
End Function

; return an attribute value as an integer
Function sdXMLAttrValueInt(node.sdxmlnode,name$,dflt=0)
ret=dflt
a.sdxmlattr = sdXMLfindattr(node,name$)
If a <> Null Then ret=avalue
Return ret
End Function

; return an attribute value as a float
Function sdXMLAttrValueFloat#(node.sdxmlnode,name$,dflt#=0)
ret#=dflt#
a.sdxmlattr = sdXMLfindattr(node,name$)
If a <> Null Then ret#=avalue
Return ret
End Function

;x.sdxmlnode = sdReadXML("test.xml")
;sdwritexml("test2.xml",x)

;f.sdxmlnode = sdxmlfindnode(x,"BB3D/NODE/MESH/")
;If f <> Null Then
; ;gak debuglog "FOUND!!!"
; sdxmldeletenode(f)
;End If

;sdwritexml("test3.xml",x)

;nl.sdxmlnodelist = sdxmlselectnodes(x,"/VERTEX/POS/")
;While nl <> Null;
; ;gak debuglog "Found....."+nl
ode ag$
; nl=nl
extnode
;Wend
;sdxmldeleteList(nl);



;sdxmldeletenode(x)


Comments :


Pedro(Posted 1+ years ago)

 thank you Blitztastic for this code : really excellent and performant.below an upgrade to use it only in read only mode.; ID: 361; Author: Blitztastic; Date: 2002-07-05 08:57:18; Title: XML code; Updated by : Philippe C; Date: 2004-07-25 ; Description: XML loading/parsing; XML load / parse functions ;; updates done:;   =>    remove Functions And Datas which are not used to load And parse. ;   =>    Add control during the read of the file in order to get syntax errors : ;      rough controls are done;   => add 2 new functions in order to simplify the access;      pXMLGetBranch : get a branch of the xml file for a given value;      pXMLGetValue : get the value of the attributes contains in the branch;      May be is not very pure XML parsing but it is convenient to use.;; WARNING : ;   IN CASE OF WRONG RESULT OPEN FIRST THE FILE WITH IE OR MOZILLA AND CHECK IF THE ;   XML FILE IS WITHOUT ERROR.;    WHILE YOU HAVE A WRONG RESULT WITH IE OR MOZILLA THIS LIBRARY WILL RETURN AN ;   ERROR MESSAGE OR A WRONG RESULT.;    NO CONTROL ARE DONE ON THE SYNTAX : FOR THIS LIBRARY THE XML FILE IS PERFECT !;   A ROUGH CONTROL HAS BEEN ADDED, BUT IT IS NOT POSSIBLE TO KNOW WHERE THE ERROR(s) COME FROM.;;_____________________________________________________________________________________________________; TYPE;_____________________________________________________________________________________________________Type sdXMLnodelist   Field node.sdxmlnode   Field nextnode.sdxmlnodelist   Field prevnode.sdxmlnodelistEnd Type; for internal use, do not use in code outside of this fileType sdXMLworklist   Field node.sdxmlnodeEnd TypeType sdXMLnode   Field tag$,value$,path$   Field fileid      ; linkage functionality   Field firstchild.sdXMLnode   Field lastchild.sdXMLnode   Field childcount   Field nextnode.sdXMLnode   Field parent.sdXMLnodeEnd TypeGlobal SDXMLFILEID;_____________________________________________________________________________________________________; FUNCTION;_____________________________________________________________________________________________________Function sdReadXML.sdXMLnode(filename$)   infile = ReadFile(filename$)   SDXMLFILEID=MilliSecs()   x.sdxmlnode = sdXMLReadNode(infile,Null)   CloseFile infile   Return xEnd Function; adds node to end of list (need separate function for insert, or mod this on)Function sdXMLAddNode(parent.sdxmlnode,node.sdxmlnode)   If parent <> Null      ;gak debuglog "Parent of node = ["+parent   ag$+"]"      If parentchildcount = 0 Then         parentfirstchild = node      Else         parentlastchild
extnode = node      End If      parentlastchild = node      parentchildcount = parentchildcount +1      nodepath$ = parentpath$+parent   ag$   End If   nodeparent = parent   nodepath$=nodepath$+"/"   ;gak debuglog "path to ["+node   ag$+"]={"+nodepath$+"}"End FunctionFunction sdXMLSelectNodes.sdxmlnodelist(node.sdxmlnode,path$,recurse=True)   root.sdxmlnodelist=Null   sdxmlselectnodesi(node,path$,recurse)   prev.sdxmlnodelist=Null      c = 0   For wl.sdxmlworklist = Each sdxmlworklist      c = c + 1      nl.sdxmlnodelist = New sdxmlnodelist      nl
ode = wl
ode      If prev = Null Then          root = nl         prev = nl      Else         prev
extnode = nl         nlprevnode = prev      End If      prev = nl      Delete wl    Next   ;gak debuglog "XML: "+c+" nodes selected"   Return rootEnd Function; internal selection function, do not use outside this fileFunction sdXMLSelectNodesI(node.sdxmlnode,path$,recurse=True)   workList.sdXMLworklist=Null   ;gak debuglog "------------- Perfoming Select ("+path$+")------------"   If node = Null Then       ;gak debuglog "Search node is null!!!"   End If   ret.sdXMLnode = Null   p=Instr(path$,"/")   If p > 0 Then       tag$=Left$(path$,p-1)      a.sdxmlnode = node      While a<>Null          ;gak debuglog "Looking for {"+path$+"} in {"+apath$+a   ag$+"/}  {"+Lower(Right$(apath$+a   ag$+"/",Len(path$)))+"} @"         If Lower(path$)=Lower(Right$(apath$+a   ag$+"/",Len(path$))) Then               workList = New sdXMLworklist               workList
ode = a               ;gak debuglog ">>FOUND"         End If         If afirstchild <> Null And (recurse) Then            sdXMLSelectNodesI(afirstchild,path$)         End If         a = a
extnode      Wend   End IfEnd FunctionFunction sdXMLReadNode.sdxmlnode(infile,parent.sdXMLnode,pushed=False)   mode = 0   root.sdxmlnode = Null   cnode.sdxmlnode = Null   x.sdXMLnode = Null   ispushed = False   done = False   errorLT = 0      ; philippe c   errorGT = 0      ; philippe c   errorSL = 0      ; philippe c   While (Not done) And (Not Eof(infile))      c = ReadByte(infile)            If c<32 Then c=32      ch$=Chr$(c);      ;gak debuglog "{"+ch$+"} "+c+" mode="+mode      Select mode        Case 0 ; looking for the start of a tag, ignore everything else         If ch$ = "<" Then             errorLT= errorLT + 1 ; philippe C            mode = 1; start collecting the tag         End If        Case 1 ; check first byte of tag, ? special tag          If ch$ = "?" Or ch$ = "!" Then             mode = 0; class special nodes as garbage & consume         Else            If ch$ = "/" Then                errorSL = errorSL + 1 ; philippe C               mode = 2 ; move to collecting end tag               ;xendtag$=ch$               ;gak debuglog "** found end tag"            Else               cnode=x                              x.sdxmlnode = New sdxmlnode               xfileid = SDXMLFILEID; global indicator to group type entries (allows multiple XML files to be used)               sdXMLaddNode(cnode,x)                           If cnode=Null Then root=x               x   ag$=ch$               mode = 3 ; move to collecting start tag            End If         End If        Case 2 ; collect the tag name (close tag)         If ch$=">" Then             errorGT= errorGT + 1 ; philippe C            mode = 0 ; end of the close tag so jump out of loop            If x = Null Then RuntimeError "error parsing : open the file with IE or MOZILLA to check you xml file and found the error"             tmptagPHC$ = x   ag            x = xparent         End If        Case 3 ; collect the tag name          If ch$=" " Then             ;gak debuglog "TAG:"+x   ag$            mode = 4 ; tag name collected, move to collecting attributes         Else             If ch$="/" Then                errorSL = errorSL + 1 ; philippe C               ;gak debuglog "TAG:"+x   ag$               mode = 2; start/end tag combined, move to close            Else               If ch$=">" Then                  errorGT= errorGT + 1 ; philippe C                  ;gak debuglog "TAG:"+x   ag$                  mode = 20; tag closed, move to collecting value               Else                  x   ag$ = x   ag$ + ch$               End If            End If         End If        Case 4 ; start to collect attributes          If Lower(ch$)>="a" And Lower(ch$)<="z" Then             aname$=ch$;             mode = 5; move to collect attribute name         Else            If ch$=">" Then               errorGT= errorGT + 1 ; philippe C               xvalue$=""               mode = 20; tag closed, move to collecting value            Else               If ch$="/" Then                   errorSL = errorSL + 1 ; philippe C                  mode = 2 ; move to collecting end tag                  ;gak debuglog "** found end tag"               End If            End If         End If        Case 5 ; collect attribute name          If ch$="=" Then           ;gak debuglog "ATT:"+aname$           aval$=""           mode = 6; move to collect attribute value         Else           aname$=aname$+ch$         End If        Case 6 ; collect attribute value          If c=34 Then            mode = 7; move to collect string value         Else            If c <= 32 Then                ;gak debuglog "ATV:"+aname$+"="+aval$               mode = 4; start collecting a new attribute            Else                  aval$=aval$+ch$            End If         End If        Case 7 ; collect string value         If c=34 Then            ;gak debuglog "ATV:"+aname$+"="+aval$            mode = 4; go and collect next attribute         Else            aval$=aval$+ch$         End If        Case 20 ; COLLECT THE VALUE PORTION         If ch$="<" Then             errorLT = errorLT + 1 ; philippe C            ;gak debuglog "VAL:"+x   ag$+"="+xvalue$            mode=1; go to tag checking         Else            xvalue$=xvalue$+ch$         End If      End Select            If Eof(infile) Then done=True      Wend      ; added by philippe C   ; control : the amount of > is equal to the amount of <      If errorLT  <>  errorGT  Then       RuntimeError "error parsing missing '< or >' : open the file with IE or MOZILLA to check the xml file and found the error(s)"   EndIf      ; control : the amount of > has to be always even      If errorLT  <> Int(errorLT/ 2) * 2 Then       RuntimeError "error parsing missing ' tag>' : open the file with IE or MOZILLA to check the xml file and found the error(s)"   EndIf      ; control : the amount of > has to be always even      If errorGT  <> Int(errorGT/ 2) * 2 Then       RuntimeError "error parsing missing '<tag ' : open the file with IE or MOZILLA to check the xml file and found the error(s)"   EndIf   ; control : the amount of / is equal to the amount of <tag> divide by 2      If  errorGT/2 <> errorSL Then       RuntimeError "error parsing missing '/' in a tag : open the file with IE or MOZILLA to check the xml file and found the error(s)"   EndIf   Return rootEnd Function;--------------------------------------------------------------------------------; functions added par Philippe c;--------------------------------------------------------------------------------Function pXmlGetBranch.sdxmlnodeList(node.sdxmlnode,path$,value$); this function return the complete xml file branch for a path and given value; e.g : path="game/players/player/uid/",value="2"   branch.sdxmlnodelist = Null      branch.sdxmlnodelist = sdxmlselectnodes(node,path)   While branch <> Null      If branch
odevalue = value         Return branch      EndIf      branch=branch
extnode   Wend      Return branch   End FunctionFunction pXmlGetValue$(node.sdxmlnode,pathValue$); this function return the value in alhpanumeric value associate to a complete path in a branch; this function has to be used with : sdXMLselectnodesValue   path.sdxmlnodelist = Null      path.sdxmlnodelist = sdxmlselectnodes(node,pathValue)      If path <> Null Then        Return path
odevalue$   Else      Return ""   EndIfEnd Function;--------------------------------------------------------------------------------; test if the xml file is ok and attributes ok. Performance test ;--------------------------------------------------------------------------------Function test(file$=""); change the value between bracket"   If Len(file) = 0 Then file = testCreateFile()      Delay 1000 ; OS close the file   timet = MilliSecs()   timeTotal = timet   x.sdxmlnode = sdReadXML(file)   time1 = MilliSecs()-timet   timet = MilliSecs()      nl.sdxmlnodelist = pXmlGetBranch(x,"game/players/player/uid/","2")   time2 = MilliSecs()-timet   timet = MilliSecs()      v1$ = pXmlGetValue(nl
ode,"game/players/player/path/")   time3 = MilliSecs()-timet   timet = MilliSecs()      v2$ = pXmlGetValue(nl
ode,"game/players/player/follow/")   time4 = MilliSecs()-timet   timet = MilliSecs()         nl = Null   time5 = MilliSecs()-timet   timet = MilliSecs()         Delete nl   time6 = MilliSecs()-timet   timet = MilliSecs()         Delete x   time7 = MilliSecs()-timet   timet = MilliSecs()      timetotal = timet - timetotal    Print "--------------"   Print "time1 = " + time1 + " ms   read the xml file"   Print "time2 = " + time2 + " ms   search a branch"   Print "time3 = " + time3 + " ms   search an attribute"   Print "time4 = " + time4 + " ms   search an attribute"   Print "time5 = " + time5 + " ms   put null into type"   Print "time6 = " + time6 + " ms   delete type"   Print "time7 = " + time7 + " ms   delete type"   Print "        ----"   Print "TOTAL = " + timeTotal + " ms"   Print "--------------"   Print " "   Print "seached value :"   Print "v1 = " + v1$   Print "v2 = " + v2$   WaitKey   End FunctionFunction testCreateFile$(file$ = "test.xml")   If FileType(file) <> 0 Then DeleteFile file   fileOut = WriteFile(file)   Restore startdata   Read number    For T = 1 To number       Read ligne$       WriteLine fileout,ligne$       Next    CloseFile fileout   ligne$ = "result stored in : " + CurrentDir() + file      For i = 1 To Len(ligne) Step 40      Print Mid$(ligne,i,40)   Next   Print    Return file$End Function;_____________________________________________________________________________________________________; to comment when the library is used in a program or uncomment to test xml filetest() ; xml file .startdataData 31Data "<game>"Data "   <players>"Data "      <player>"Data "         <uid>1</uid>"Data "         <mouseAuthorised>1</mouseAuthorised>"Data "         <keyboardAuthorised>1</keyboardAuthorised>"Data "         <automatic>0</automatic>"Data "         <path>PATH1</path>"Data "         <follow>NO</follow>"Data "         <playerType>1</playerType>"Data "      </player>"Data "      <player>"Data "         <uid>2</uid>"Data "         <mouseAuthorised>1</mouseAuthorised>"Data "         <keyboardAuthorised>1</keyboardAuthorised>"Data "         <automatic>0</automatic>"Data "         <path>PATH2</path>"Data "         <follow>YES</follow>"Data "         <playerType>1</playerType>"Data "      </player>"Data "      <player>"Data "         <uid>3</uid>"Data "         <mouseAuthorised>1</mouseAuthorised>"Data "         <keyboardAuthorised>1</keyboardAuthorised>"Data "         <automatic>0</automatic>"Data "         <path>PATH3</path>"Data "         <follow>NO</follow>"Data "         <playerType>1</playerType>"Data "      </player>"Data "   </players>"Data "</game>";_____________________________________________________________________________________________________