Code archives/File Utilities/XML code
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
Will add further comments/descriptions later | |||||
; 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\tag$=tag$ x\fileid = 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\tag$+"]" If node\parent <> Null Then ;gak debuglog "Returning to parent ["+node\parent\tag$+"]" Else ;gak debuglog "No Parent found" End If Return node\parent 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\tag$+"]" If parent\childcount = 0 Then parent\firstchild = node Else parent\lastchild\nextnode = node End If node\prevnode = parent\lastchild parent\lastchild = node parent\childcount = parent\childcount +1 node\path$ = parent\path$+parent\tag$ End If node\parent = parent node\path$=node\path$+"/" ;gak debuglog "path to ["+node\tag$+"]={"+node\path$+"}" End Function Function sdXMLDeleteNode(node.sdxmlnode) n.sdxmlnode = node\firstchild ; delete any children recursively While n <> Null nn.sdxmlnode= n\nextnode sdXMLdeletenode(n) n = nn Wend ; delete attributes for this node a.sdxmlattr = node\firstattr While a <> Null na.sdxmlattr = a\sibattr Delete a a = na Wend ; dec parents child count If node\parent <> Null node\parent\childcount = node\parent\childcount -1 ; heal linkages If node\prevnode <> Null Then node\prevnode\nextnode = node\nextnode If node\nextnode <> Null Then node\nextnode\prevnode = node\prevnode If node\parent\firstchild = node Then node\parent\firstchild = node\nextnode If node\parent\lastchild = node Then node\parent\lastchild = node\prevnode End If ; delete this node ; ;gak debuglog "DELETING:"+node\tag$ 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\tag$+"]" If Lower(tag$)=Lower(a\tag$) Then If p=Len(path$) Then ;gak debuglog "Found..." ret = a Else If a\firstchild <> Null Then ret = sdxmlfindnode(a\firstchild,Mid$(path$,p+1)) End If End If End If a = a\nextnode Wend End If Return ret End Function Function sdXMLDeleteList(nl.sdxmlnodelist) While nl <> Null na.sdxmlnodelist = nl\nextnode 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\node = wl\node If prev = Null Then root = nl prev = nl Else prev\nextnode = nl nl\prevnode = 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 {"+a\path$+a\tag$+"/} {"+Lower(Right$(a\path$+a\tag$+"/",Len(path$)))+"} @" If Lower(path$)=Lower(Right$(a\path$+a\tag$+"/",Len(path$))) Then wl = New sdXMLworklist wl\node = a ;gak debuglog ">>FOUND" End If If a\firstchild <> Null And (recurse) Then sdXMLSelectNodesI(a\firstchild,path$) End If a = a\nextnode Wend End If End Function Function sdXMLNextNode.sdXMLnode(node.sdXMLnode) Return node\nextnode End Function Function sdXMLPrevNode.sdXMLnode(node.sdXMLnode) Return node\prevnode End Function Function sdXMLAddAttr(node.sdxmlnode,name$,value$) ;gak debuglog "XML:adding attribute "+name$+"="+value$+" ("+Len(value$)+")" a.sdxmlattr = New sdxmlattr a\name$ = name$ a\value$ = value$ If node\attrcount = 0 Then node\firstattr = a Else node\lastattr\sibattr = a End If node\lastattr=a node\attrcount = node\attrcount + 1 a\parent = 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 x\endtag$=ch$ ;gak debuglog "** found end tag" Else cnode=x x.sdXMLnode = sdXMLOpennode(cnode) If cnode=Null Then root=x x\tag$=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 x\endtag$ = x\endtag$ + ch$ End If Case 3 ; collect the tag name If ch$=" " Then ;gak debuglog "TAG:"+x\tag$ mode = 4 ; tag name collected, move to collecting attributes Else If ch$="/" Then ;gak debuglog "TAG:"+x\tag$ x\endtag$=x\tag$ mode = 2; start/end tag combined, move to close Else If ch$=">" Then ;gak debuglog "TAG:"+x\tag$ mode = 20; tag closed, move to collecting value Else x\tag$ = x\tag$ + 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 x\value$="" mode = 20; tag closed, move to collecting value Else If ch$="/" Then mode = 2 ; move to collecting end tag x\endtag$=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\tag$+"="+x\value$ mode=1; go to tag checking Else x\value$=x\value$+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\tag$+".." s$="<"+node\tag$ a.sdxmlattr = node\firstattr While a<>Null ; ;gak debuglog "Writing attr ["+a\name$+"]=["+a\value$+"]" s$ = s$+" "+Lower(a\name$)+"="+Chr$(34)+a\value$+Chr$(34) a = a\sibattr Wend If node\value$="" And node\childcount = 0 Then s$=s$+"/>" et$="" Else s$=s$+">"+node\value$ et$="</"+node\tag$+">" End If WriteLine outfile,sdXMLcleanStr$(tab$+s$) n.sdxmlnode = node\firstchild While n <> Null sdXMLwriteNode(outfile,n,tab$+" ") n = n\nextnode 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 = node\firstattr done = False While ret=Null And a<>Null If Lower(name$)=Lower(a\name$) Then ret = a End If a = a\sibattr 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$=a\value$ 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=a\value 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#=a\value 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\node\tag$ ; nl=nl\nextnode ;Wend ;sdxmldeleteList(nl); ;sdxmldeletenode(x) |
Comments
| ||
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.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 fileid ; linkage functionality Field firstchild.sdXMLnode Field lastchild.sdXMLnode Field childcount Field nextnode.sdXMLnode Field parent.sdXMLnode End Type Global SDXMLFILEID ;_____________________________________________________________________________________________________ ; FUNCTION ;_____________________________________________________________________________________________________ Function sdReadXML.sdXMLnode(filename$) infile = ReadFile(filename$) SDXMLFILEID=MilliSecs() x.sdxmlnode = sdXMLReadNode(infile,Null) CloseFile infile Return x 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\tag$+"]" If parent\childcount = 0 Then parent\firstchild = node Else parent\lastchild\nextnode = node End If parent\lastchild = node parent\childcount = parent\childcount +1 node\path$ = parent\path$+parent\tag$ End If node\parent = parent node\path$=node\path$+"/" ;gak debuglog "path to ["+node\tag$+"]={"+node\path$+"}" 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\node = wl\node If prev = Null Then root = nl prev = nl Else prev\nextnode = nl nl\prevnode = 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) 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 {"+a\path$+a\tag$+"/} {"+Lower(Right$(a\path$+a\tag$+"/",Len(path$)))+"} @" If Lower(path$)=Lower(Right$(a\path$+a\tag$+"/",Len(path$))) Then workList = New sdXMLworklist workList\node = a ;gak debuglog ">>FOUND" End If If a\firstchild <> Null And (recurse) Then sdXMLSelectNodesI(a\firstchild,path$) End If a = a\nextnode Wend End If 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 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 ;x\endtag$=ch$ ;gak debuglog "** found end tag" Else cnode=x x.sdxmlnode = New sdxmlnode x\fileid = SDXMLFILEID; global indicator to group type entries (allows multiple XML files to be used) sdXMLaddNode(cnode,x) If cnode=Null Then root=x x\tag$=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\tag x = x\parent End If Case 3 ; collect the tag name If ch$=" " Then ;gak debuglog "TAG:"+x\tag$ mode = 4 ; tag name collected, move to collecting attributes Else If ch$="/" Then errorSL = errorSL + 1 ; philippe C ;gak debuglog "TAG:"+x\tag$ mode = 2; start/end tag combined, move to close Else If ch$=">" Then errorGT= errorGT + 1 ; philippe C ;gak debuglog "TAG:"+x\tag$ mode = 20; tag closed, move to collecting value Else x\tag$ = x\tag$ + 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 x\value$="" 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\tag$+"="+x\value$ mode=1; go to tag checking Else x\value$=x\value$+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 root End 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\node\value = value Return branch EndIf branch=branch\nextnode Wend Return branch End Function Function 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\node\value$ Else Return "" EndIf End 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\node,"game/players/player/path/") time3 = MilliSecs()-timet timet = MilliSecs() v2$ = pXmlGetValue(nl\node,"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 Function Function 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 Return file$ End Function ;_____________________________________________________________________________________________________ ; to comment when the library is used in a program or uncomment to test xml file test() ; xml file .startdata Data 31 Data "<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>" ;_____________________________________________________________________________________________________ |
Code Archives Forum