RIFX¨MV93imap,~mmap8( ÿÿÿÿRIFX¨imap —*ümmap8, im$KEY*ülCAStNºCASt 8SàCASt ` DRCFTpfree ÿÿÿÿCAS*  Lctx„|Èjunk¨ junk§úÿÿÿÿCinf6ÌVERS ¨ Lnam ¢RLscrÎ}TLscr˜”*Lscr €—Êfree free free KEY*ü  CAS* CinfDRCF LctxVERSVERSVERSVERSVERSVERS ccl DRCFTT~~V<. ^æCinf6 æbÀCAS* CAStNº N¬ NN&N&N&N&N:N:NNNNNNNNNb-- ©1999 Andrew White for Cathode -- andyw@cathode.co.uk -- Version 1.0.3 -- Change history -- Version 1.0.3 -- 28 SEP 1999: Fixed bug in count due to dot syntax failure of me.list.count -- 27 SEP 1999: Added getText method -- 27 SEP 1999: Fixed bug in makeList due to dot syntax failure of me.list.count -- 12 SEP 1999: Changed parseAttributes to allow more lenient handling of white -- space in attributes, specifically to allow whitespace between -- the attribute name, equals sign and attribute value. -- Strictly this is a WF error but since it causes a infinite loop -- in the old version it's best to change the code to allow it. -- Version 1.0.2 -- 06 SEP 1999: Fixed bug with PUBLIC DOCTYPE declarations -- 05 SEP 1999: Added count property and count method to override the default -- behavior of the count property which is to return the number -- of properties in the object -- Version 1.0.1 -- 04 JUL 1999: Added makeDocument method to support creation of documents -- 04 JUL 1999: Changed behavior of getElementByName to return element rather -- than a list if there's only one element with that name -- 04 JUL 1999: parseElement now sets whether the element is empty or not. -- This is to support creation of documents from a node tree -- 04 JUL 1999: decodeEntities now supports hex encoded entities -- Version 1.0 -- 01 JUL 1999: Original Release -- Description -- The xml.parser class implements a Lingo parser which is -- functionally equivalent to the XML Parser Xtra - minus the bugs :-) -- To replace the xtra version with the Lingo version just change -- the new(xtra "XMLParser") to new(script "xml.parser") and everything -- should work fine. If you find any bugs please send reports to the -- email address above. -- This Lingo version implements additional functionality to aid -- access to the XML node tree. These are: -- 1. getElementByID -- This method returns the element with the unique ID passed in -- Note that if the XML document contains elements with the same -- ID then only the last element with that ID is returned. -- 2. getElementByName -- This method returns the tag (or list of tags) with the tag name -- passed in. If the tag name "*" is used then all element tags are -- returned. If your document is all elements then this is an efficient -- way to access those elements. -- 3. Bracket access -- The getAt method is overidden in the xml.node class to provide shortened -- bracket access e.g., to get a sub node you can do this: -- parser["document"]["html"]["body"] -- Without this access method you'd have to find the 'document' node manually -- from the parser.child property and then find the 'html' from the 'document' -- node and so on until you reach the depth that you want. -- To recreate the XML document from the XML node tree use makeDocument(). -- Note that the DTD is not written out as entities are fully parsed and it -- would be excessive to try and recreate arbitary entities. -- If you wish to maintain document formatting then parse the document with -- ignoreWhiteSpace set to false (use the ignoreWhiteSpace(trueOrFalse) method) -- otherwise the document will be written in a condensed format. -- Public properties property child property count -- Private properties property _ignoreWhiteSpace property _doneParsing -- Private net op properties property _cbMethod property _cbObject property _netID -- Private parser properties property _whiteSpace property _entityList property _docType property _errorStr property _idList property _tagList on new me -- Constructor method -- Initialise some properties me.child = [] me._ignoreWhiteSpace = TRUE me._doneParsing = TRUE me._errorStr = "" -- Define the XML whitespace chars me._whiteSpace = SPACE & RETURN & TAB & numToChar(10) return me end -- Public API on parseURL me, url, cbMethod, cbObject -- Functionally equivalent to the Xtra's method -- except for that you can use this one without -- crashing the machine me._cbMethod = cbMethod me._cbObject = cbObject me._netID = getNetText(url) me._doneParsing = FALSE (the actorList).add(me) end on parseString me, xmlString -- Main parser method - functionally equivalent to the Xtra's -- method of the same name, but fixes a key bug with entities -- having padded spaces around them -- Initialise the storage lists for XML nodes me.child = [] me._idList = [:] me._tagList = [:] -- Initialise the entity storage list and add the default entities me._entityList = [:] me._entityList.addProp("lt","<") me._entityList.addProp("gt",">") me._entityList.addProp("amp","&") me._entityList.addProp("apos","'") me._entityList.addProp("quot",QUOTE) -- Initialise the node stack variables currentNode = me me.count = 0 elementStack = [] -- Break up the xml string into tokenized chunks xmlTokens = new(script "xml.tokenizer", xmlString, "<>", TRUE) -- Scan through the token list and handle the tags appropriately repeat while xmlTokens.hasMoreTokens() token = xmlTokens.nextToken() -- If the token is a '<' this is a start of an element -- and sets of a sequence of events. if token = "<" then token = xmlTokens.nextToken() case token.char[1] of "?": -- PROCESSING INSTRUCTION node if token.char[2..4] <> "xml" then currentNode.child.append(me.parseProcInst(token)) end if "!": -- Either a DOCTYPE, CDATA or COMMENT section case token.char[1..3] of "!DO": -- If it's a DOCTYPE then parse the tag and -- continue parsing tokens until we reach the -- end of the DOCTYPE as whitespace is ignored -- inside of the internal DTD me.parseDocType(token) if token contains "[" then repeat while xmlTokens.hasMoreTokens() token = xmlTokens.nextToken() -- The end of the DTD so jump out of the repeat if token contains "]" then exit repeat end if -- Since we are not a validating parser we -- only need to worry about ENTITY definitions case token.char[1..3] of "!EN": me.parseEntity(token) end case end repeat end if "!--": -- With a comment node all we do is scan for the end -- of the comment and ignore the contents repeat while xmlTokens.hasMoreTokens() newToken = xmlTokens.nextToken() if newToken = ">" then if token.char[(token.length - 1)..(token.length)] = "--" then exit repeat end if end if token = newToken end repeat "![C": -- With CDATA sections just scan for the end and add the -- whole chunk to the node tree with any further parsing repeat while xmlTokens.hasMoreTokens() newToken = xmlTokens.nextToken() if newToken = ">" then if token.char[(token.length - 1)..(token.length)] = "]]" then textNode = me.parseCDATA(token) if textNode.ilk = #instance then currentNode.child.append(textNode) end if exit repeat end if end if token = token & newToken end repeat end case "/": -- closing element tag so we pop the -- parent element off the stack if elementStack.count then currentNode = elementStack[1] elementStack.deleteAt(1) currentNode.count = currentNode.count + 1 end if otherwise -- It must be just a general element so -- we parse it in the standard way -- If it's an empty element then just append -- it to the current child list otherwise -- push the current element onto the stack and -- set the new element to be the current element if token.char[token.length] = "/" then delete token.char[token.length] newNode = me.parseElement(token, TRUE) currentNode.child.append(newNode) currentNode.count = currentNode.count + 1 else elementStack.addAt(1, currentNode) newNode = me.parseElement(token, FALSE) currentNode.child.append(newNode) currentNode = newNode currentNode.count = 0 end if end case else if token = ">" then -- do nothing else -- Text nodes are not allowed outside of the -- root document node so check that we are -- not at the parser level if currentNode <> me then -- Call the parseText method to handle -- whether the text has whitespace stripped -- from it or not textNode = me.parseText(token) if textNode.ilk = #instance then currentNode.child.append(textNode) end if end if end if end repeat end on ignoreWhiteSpace me, ignore -- Mutator method for ignoring whitespace -- Defaults to TRUE me._ignoreWhiteSpace = ignore end on doneParsing me -- Accessor method for checking whether a -- parseURL command has completed return me._doneParsing end on makeList me -- Functionally equivalent to the Xtra's makeList() -- method. It returns a formatted property list of -- the XML documents structure. -- I recommend that you use the dot syntax and/or -- the extended API for more efficient access to -- the document's nodes docList = [:] childList = ["!ATTRIBUTES": [:]] repeat with node in me.child case node.type of #element: childList.addProp(node.name, node.toList()) #procInst: childList.addProp("!PROCINST", node.toList()) #charData: childList.addProp("!CHARDATA", node.toList()) end case end repeat if count(me.child) then docList.addProp("ROOT OF XML DOCUMENT", childList) end if return docList end on getError me -- Returns any network error that occurs when parsing an URL -- This Lingo parser is very loose on errors -- compared to the Xtra and will try to continue to -- parse a document even though the document might -- not be well-formed. This is not what the XML spec -- requires and so this parser will get more strict -- once a efficient error handling method can be -- determined return me._errorStr end -- Extended api on getAt me, index -- Accessor method to implement [] access for subnodes. -- e.g.: parser["document"]["form"]["element"] -- If the index value is an integer then get the subnode by -- postion, otherwise search for a matching node name. -- It only returns the first matching node name if index.ilk = #integer then return me.child[index] else index = string(index) repeat with node in me.child if node.name = index then return node end if end repeat end if end on count me -- Return the number of children for this node return count(me.child) end on getElementByID me, ID -- Accessor method for elements with UIDs return me._idList[ID] end on getElementByName me, tagName -- Accessor method for returning element(s) -- with a particular tag name. The "*" wildcard -- returns all element nodes if tagName = "*" then return me._tagList else elemList = me._tagList[tagName] if elemList.count > 1 then return elemList else return elemList[1] end if end if end on getText me -- Return all of the text under this node str = "" repeat with node in me.child str = str & node.getText() end repeat return str end on makeDocument me -- Build an XML document based on the current nodes -- Insert the xml declaration xmlDoc = "" & RETURN -- The DTD should be inserted here but since entities are -- fully parsed there's no point since the nodes themselves -- will only contain basic character entities -- Append the document nodes repeat with node in me.child xmlDoc = xmlDoc & node.toString() & RETURN end repeat return xmlDoc end -- Private methods on stepFrame me -- Psuedo-thread method for fetching a remote xml document if netDone(me._netID) then if netError(me._netID) = "OK" then xmlDoc = netTextResult(me._netID) me.parseString(xmlDoc) else me._errorStr = "net error:" && netError(me._netID) end if me._doneParsing = TRUE -- Callback on parse completion if me._cbMethod.ilk <> #void then if me._cbObject.ilk = #void then do (me._cbMethod && "me") else call(me._cbMethod, me._cbObject, me) end if end if end if end on parseProcInst me, tokenStr -- Private method for parsing PI nodes delete tokenStr.char[tokenStr.length] delete tokenStr.char[1] piName = tokenStr.word[1] piData = tokenStr.word[2..(tokenStr.word.count)] piNode = new(script "xml.node", piName, #procInst, piData) return piNode end on parseDocType me, tokenStr -- Private method for parsing DOCTYPE nodes me._docType = tokenStr.word[2] end on parseEntity me, tokenStr -- Private method for parsing ENTITY declarations entityName = tokenStr.word[2] -- We don't need to handle paramter entities if entityName <> "%" then entityValue = tokenStr.word[3..(tokenStr.word.count)] delete entityValue.char[entityValue.length] delete entityValue.char[1] entityValue = me.decodeEntities(entityValue) if not me._entityList.findPos(entityName) then me._entityList.addProp(entityName, entityValue) end if end if end on parseCDATA me, tokenStr -- Private method for parsing CDATA sections delete tokenStr.char[(tokenStr.length - 1)..(tokenStr.length)] delete tokenStr.char[1..8] if tokenStr.length then return new(script "xml.node", VOID, #charData, tokenStr) else return VOID end if end on parseElement me, tokenStr, isEmpty -- Private method for parsing ELEMENT nodes elementName = tokenStr.word[1] elementNode = new(script "xml.node", elementName, #element, VOID) elementNode.isEmpty = isEmpty -- If we have attributes then parse them if offset("=", tokenStr) then attributeStr = tokenStr.word[2..(tokenStr.word.count)] attributeList = me.parseAttributes(attributeStr) elementNode.attributeValue = attributeList numAttributes = attributeList.count repeat with i = 1 to numAttributes elementNode.attributeName.append(attributeList.getPropAt(i)) end repeat -- If the element has a UID then add to the list for getElementByID if attributeList.findPos("id") then me._idList.setaProp(attributeList["id"], elementNode) end if end if -- Add an element to the getElementByName list if not me._tagList.findPos(elementName) then me._tagList.addProp(elementName,[elementNode]) else tagList = me._tagList[elementName] tagList.append(elementNode) end if return elementNode end on parseAttributes me, attrStr -- Private method for parsing the attributes of an element attrList = [:] attrTokens = new(script "xml.tokenizer", attrStr, QUOTE & "'=" & me._whiteSpace, TRUE) repeat while attrTokens.hasMoreTokens() token = attrTokens.nextToken() -- Eat up any whitespace repeat while me._whiteSpace contains token token = attrTokens.nextToken() end repeat -- First token is the attribute name attrName = token -- Eat up the equals token repeat while token <> "=" token = attrTokens.nextToken() end repeat -- Set the enclosing quote type for this attribute quoteType = attrTokens.nextToken() repeat while (quoteType <> "'") and (quoteType <> QUOTE) quoteType = attrTokens.nextToken() end repeat -- Build up the attribute value until we hit the end quote token = attrTokens.nextToken() attrValue = "" repeat while token <> quoteType attrValue = attrValue & token token = attrTokens.nextToken() end repeat -- Decode any entities in the attribute value attrValue = me.decodeEntities(attrValue) -- Store the name-value pair attrList.addProp(attrName,attrValue) end repeat return attrList end on parseText me, tokenStr -- Private method for parsing text sections textStr = "" if me._ignoreWhiteSpace then -- Tokenise the text based on whitespace and -- then ignore that white space. Append the -- tokens together using a single space tokens = new(script "xml.tokenizer", tokenStr, me._whiteSpace) if tokens.hasMoreTokens() then textStr = me.decodeEntities(tokens.nextToken()) end if repeat while tokens.hasMoreTokens() textToken = tokens.nextToken() textStr = textStr && me.decodeEntities(textToken) end repeat else textStr = me.decodeEntities(tokenStr) end if if textStr.length then return new(script "xml.node", VOID, #charData, textStr) else return VOID end if end on decodeEntities me, str -- Private method for decoding entities (&#xxx;) -- This needs to be done for text sections and with -- element attributes if offset("&", str) and offset(";", str) then tokens = new(script "xml.tokenizer", str, "&;", TRUE) decodedStr = "" repeat while tokens.hasMoreTokens() token = tokens.nextToken() if token = "&" then entityName = tokens.nextToken() if entityName.char[1] = "#" then if entityName.char[2] = "x" then -- This is a real hack :-) -- Rather than implementing a hexToDec method we bend -- the color object to our needs. This will only work -- for ASCII & UTF8 encoded XML files entityValue = numToChar(rgb(entityName.char[3..4] & "FFFF").red) else entityValue = numToChar(entityName.value) end if else entityValue = me._entityList.getaProp(entityName) end if decodedStr = decodedStr & entityValue tokens.nextToken() else decodedStr = decodedStr & token end if end repeat return decodedStr else return str end if end xml.parserH0u²²H0uôô,CASt 8 * † ” ” ” ” ¨ ¨ ¼ ¼ ¼ ¼ Ð Ð Ø-- ©1999 Andrew White for Cathode -- andyw@cathode.co.uk -- Version 1.0 -- Change history -- 1 JUL 99: Original Release -- Description -- The xml.tokenizer class implements a Lingo version of the -- Java tokenizer. This class is used to break up the xml string -- into bite-sized chunks for the parser. -- It can handle multiple delimiter chars and can optionally -- return the delimiter chars in the token stream if they -- help provide contextual information. -- Private properties property _tokenList property _currPos on new me, str, delims, returnTokens -- Constructor method. The majority of work is done here -- Set the default values for the delims and return tokens -- if the user didn't specify those in the new() method call case (the paramCount) of 2: delims = " " & TAB & RETURN returnTokens = FALSE 3: returnTokens = FALSE end case me._tokenList = [] numDelims = delims.length delimList = [] -- Test each delim char to see whether it occurs in the -- search string. This can provide a small speed gain by -- not testing for delims that aren't there. repeat with i = 1 to numDelims delimChar = delims.char[i] if offset(delimChar, str) then delimList.add(delimChar) end if end repeat -- Test each delim char and find the minmum offset value. -- Then add the string upto that point as a token. If we're -- returning the delim chars then add that. Repeat until -- there are no more delim chars in the remaining string repeat while str.length offsetList = [] repeat with j in delimList charOffset = offset(j, str) if charOffset then offsetList.add(charOffset) end if end repeat if offsetList.count then tokenOffset = min(offsetList) if tokenOffset > 1 then me._tokenList.add(str.char[1..(tokenOffset - 1)]) end if if returnTokens then me._tokenList.add(str.char[tokenOffset]) end if delete str.char[1..tokenOffset] else me._tokenList.add(str) str = "" end if end repeat -- Set the initial position for nextToken() me._currPos = 1 return me end -- Public API on countTokens me -- Simple accessor for querying the number of tokens return me._tokenList.count end on hasMoreTokens me -- Simple accessor method for querying whether we're at -- the end of the token list if me._currPos <= me._tokenList.count then return TRUE else return FALSE end if end on nextToken me -- Simple iterator method for walking through the token list if me._currPos <= me._tokenList.count then token = me._tokenList[me._currPos] me._currPos = me._currPos + 1 return token else return VOID end if end xml.tokenizerˆÔ½ † †ˆÔ½ÔÔ,ý· XCASt  ’       4444H-- ©1999 Andrew White for Cathode -- andyw@cathode.co.uk -- Version 1.0.3 -- Change history -- Version 1.0.3 -- 28 SEP 1999: Fixed bug in count due to dot syntax failure of me.list.count -- 28 SEP 1999: Fixed bug in attrString due to dot syntax failure of me.list.count -- 27 SEP 1999: Added getText method -- 07 SEP 1999: Added getElementByName method -- Version 1.0.2 -- 05 SEP 1999: Added count property and count method to override the default -- behavior of the count property which is to return the number -- of properties in the object -- Version 1.0.1 -- 04 JUL 1999: added isEmpty private property to store whether the element -- is empty or not. This is to support document creation, as -- we need to write a '/>' end to the tag of an empty element -- 04 JUL 1999: added toString method to support creation of documents -- 04 JUL 1999: added attrString method to support creation of documents -- 04 JUL 1999: added encodeString method to support creation of documents -- Version 1.0 -- 01 JUL 1999: Original Release -- Description -- The xml.node class implements a generic node of an XML document. -- This a private class of the XML parser and implements the dot access -- equivalent of the XML Parser Xtra. -- Public properties property name property type property text property child property count property attributeName property attributeValue -- Private properties property isEmpty on new me, _name, _type, _data -- Constructor method. me.name = _name me.type = _type me.text = _data me.child = [] me.attributeName = [] me.attributeValue = [:] return me end -- Public API on makeSublist me -- Accesor method to return a property list of the elements contents -- Functionaly equivalent to the XML Parser Xtra's makeSubList() method case me.type of then #element: xmlList = [:] xmlList.addProp(me.name, me.toList()) #procInst: xmlList = [:] xmlList.addProp("!PROCINST", me.toList()) #charData: xmlList = [:] xmlList.addProp("!CHARDATA", me.toList()) end case return xmlList end -- Extended API on getAt me, index -- Accessor method to implement [] access for subnodes. -- e.g.: parser["document"]["form"]["element"] -- If the index value is an integer then get the subnode by -- postion, otherwise search for a matching node name. -- It only returns the first matching node name if index.ilk = #integer then return me.child[index] else index = string(index) repeat with node in me.child if node.name = index then return node end if end repeat end if end on count me -- Return the number of children for this node return count(me.child) end on getElementByName me, tagName, nodeList -- Accessor method to return all elements of a particular name if nodeList.ilk = #void then -- If the nodeList is void then initialise nodeList = [] end if -- Iterate through the child nodes and if it is an element then -- call this method recursively, passing in the current node list repeat with node in me.child if node.type = #element then -- If the node's name matches add it to the nodeList if node.name = tagName then nodeList.add(node) end if -- Call ourselves recursively node.getElementByName(tagName,nodeList) end if end repeat -- If there's only one node then return -- that node rather than a list if nodeList.count = 1 then return nodeList[1] else return nodeList end if end on getText me -- Return all of the text under this node case me.type of -- If it's a char data node then we just -- return the text property - char data nodes -- have no children #charData: return me.text -- For every node in the child list call getText -- recursively to build up all of the text beneath -- this node #element: str = "" repeat with node in me.child str = str & node.getText() end repeat return str -- Return the processing instruction #procInst: return me.text end case end -- Private API on toList me -- Private method to return a property list in the same -- format as the XML Parser Xtra. case me.type of #element: elemList = [:] attrList = duplicate(attributeValue) elemList.addProp("!ATTRIBUTES", attrList) repeat with i in child case i.type of #element: elemList.addProp(i.name, i.toList()) #charData: elemList.addProp("!CHARDATA", i.toList()) #procInst: elemList.addProp("!PROCINST", i.toList()) end case end repeat return elemList #charData: return me.text #procInst: piList = [:] piList.addProp("NAME", me.name) piList.addProp("TEXT", me.text) return piList end case end on toString me -- Private method to return an XML node's string -- representation for inserting into a document case me.type of #element: if me.isEmpty then tag = "<" & me.name & me.attrString() & "/>" else tag = "<" & me.name & me.attrString() & ">" repeat with node in me.child tag = tag & node.toString() end repeat tag = tag & "" end if return tag #charData: return me.encodeString(me.text) #procInst: return ("") end case end on attrString me -- Private method for building the attributes of -- an element as a string to be inserted into a tag numAttr = count(me.attributeValue) attrStr = "" if numAttr then repeat with i = 1 to numAttr attrName = attributeValue.getPropAt(i) attrValue = me.encodeString(attributeValue.getAt(i)) attrStr = attrStr && attrName & "=" & QUOTE & attrValue & QUOTE end repeat end if return attrStr end on encodeString me, str -- Private method to encode strings for insertion -- into an XML document encodedStr = "" numChars = str.length repeat with i = 1 to numChars currChar = str.char[i] case currChar of "<": encodedStr = encodedStr & "<" ">": encodedStr = encodedStr & ">" "'": encodedStr = encodedStr & "'" QUOTE: encodedStr = encodedStr & """ "&": encodedStr = encodedStr & "&" otherwise charNum = charToNum(currChar) if charNum > 127 then encodedStr = encodedStr & "&#" & charNum & ";" else encodedStr = encodedStr & currChar end if end case end repeat return encodedStr end xml.nodeüþgÿÎüþgÿÎLL,Lctx„` ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ i\¨ i\ i[¸LscrÎÎÎ\ÿÿÿÿÿÿÎ \vvJú„J "*_()ÿÿ8JLL<bLÿÿ)Z„ŒŒkv Œÿÿ˜¨¬º¬†Àºÿÿz‚††'ÈJ†ÿÿ Œ–˜˜(ST˜ÿÿ±ž P R X(Ú^! Xÿÿ z „ † †+îƒ †ÿÿ_ ” ô ø ú-¼– úÿÿ  " "/Þ± " ÿÿ $ 6 : :0E· : ÿÿE > „ ˆ Š0°¿ Š ÿÿ= œ Ú Ü à2$Õ à ÿÿV è > @ D2Òá D ÿÿŒ V â ä æ4Þú æÿÿo  t x ~7M ~ÿÿ Š ž ¢ ¢8†+ ¢ÿÿ… ¦ , 0 48ÿ4 4ÿÿg H ° ´ ´;K ´ÿÿù ÀºÀÎ:;@          KKbAKaBWCR„CCRKadCWAdd •pddCWRL¡Bd…C•LL¡DLC§EB§+“:d…F•L„LC§EB§+“d…G•L„LC§EB§+eA”reKaCV•L„LB§+LBWIHJ     KaBWK¡3…K•KEKC§0BW“CKC—LQKadCWAdd •$ddCWRL¡DK• LBWA”&eMJ   KaCVBW K…(KC§0BWNK„ •K¡)BW“2K…)KC§0RLa• LBW“LCgBWOP  „(RKadCWAdd •ddCWRLLCg RA” eLBWQJ „0„8 „@ „H „P „X RKadCWAdd •#ddCWRLLC§R „` RA”%eLBWSJK¡"C—T•K¡"C—U„h•K¡"C—VRKLBg“K„pK¡"C—U bKbKa¡3…W•2K¡ ¡3…W•Ka„x B—X“KaK¡ KB—YS  m…/K¡2C§6B§7m…/C§6B§7K…ZC§0RK…ZK…ZCgC§0R„€C—,L…FLCWRLBW[\]^KK…ZC§0¢_[K…ZC§0RL„ˆ•oK…ZK…ZCgC§0Rm…/L¡2C§6B§7m…/C§6B§7KLCgRK¡*LC§`•K¡*LLB§+[ab  m…/K¡2K¡2C§6B§7m…/C§6B§7K¡2• „C—,C—W…GKCWBW“ C—WBW[  K…ZC§0R„˜C—,L…CC—WCWRLK¢c„ KC—d•K…ZK…ZCgC§0RKLCgRLL¢eLaR R(L(L •!L¡fLL(C§gB§1L(R(”#L„¨C§`•K¡(L„°CgLB§hK¡)LC§`•K¡)LLCB§+“K…)LC§0R0L0LB§1LBW[ckmnjlio     CR„¸C—,K„À„È Ka CWRLC§-•LC§.RKaL•LC§.RTLRL„ЕLC§.RTLC§.R L „ØL „à•LC§.R TLC§.R„èR(LL •L(L R(LC§.RTKL(CgR(LLL(B§+”¡LBWpsr>tuq       „ðRKa•V„øC—,KKaCWRLC§-•KLC§.CgRLC§-•LC§.RLKLCg R” “ KKCgRL¡2• „C—,C—W…GLCWBW“ C—WBW[xvw    „KC—d„KC—d•ЄC—,K„ CWR„(RLC§-•¢LC§.RL„0•†LC§.RL…/C§0„8•JL…/C§0„@•(L…/C§0„H C—y¡zCWR “L¡{CWR “K¡*LC§|R LL RLB§.“ LL R”¦LBW“ KBWQv}>ab "   (.6<FLV\nv|‚Š˜ž¤¬´ºÂÊÐØÞäêú06<PV^dlrx€˜¦¬ºÈÎÖÞðöþ .<BHZbhntz  lt<gt>amp&apos'quot"xml.tokenizer<><?xml!!DO[]!EN!-->--![C>]]//> !ATTRIBUTES !PROCINST !CHARDATAROOT OF XML DOCUMENT*  OK net error:me xml.node% xml.node xml.node=ididxml.tokenizer"'=='"xml.tokenizer xml.node&;xml.tokenizer&;&#xFFFFLscr˜˜˜\ÿÿÿÿÿÿ˜\```€€‚ÿÿRZbrRr~ÿÿÄÒÔÔ .pÔ-ÿÿ"Úüþþ ¥y þ.ÿÿDLNP {‡PC¦d•DD D QQ“d•QeKC¢€K¡2RCRRLL •1K…/LC§0RLKC—d• LLB§$LR”3K¡2•ÃCR LdCWAdd •,ddCWR(L(KC—dR0L0• L L0B§$A”.eL a•gL C—R8L8• K¡€K…/L8C§0B§$K•K¡€K…/L8C§0B§$m…/L8C§6B§7“K¡€KB§$DQ”ÅK¢‚KBWQ„ƒˆ‰i‹…†Š‡        K…€CgBW K¡‚K…€Cg • BW“BW K¡‚K…€Cg •+K…€K¡‚C§0RKK¡‚¢‚LBW“ C—WBW>     Lscr € € €\ÿÿÿÿÿÿ €\l l!^ fDBfecÿÿ3DLL»0 LŒÿÿqZÌÎУCÐÿÿ_æFJL«_Lÿÿ bprr Ãxr ÿÿƒtøþ ,~$ ÿÿ|$ ¢¦¦¦EÿÿþÄÂÄÌ3Ê#ÌRÿÿÑðÂÄÈ`ñ ÈÿÿdèLNXXŽÿÿÀn.2</"<>=""<<>>''""&&&#;Lnam ŒŒžnewparseURL parseStringignoreWhitespace doneParsingmakeListgetErrorgetAtcountgetElementByIDgetElementByNamegetText makeDocument stepFrame parseProcInst parseDocType parseEntity parseCDATA parseElementparseAttributes parseTextdecodeEntitieschild_ignoreWhiteSpace _doneParsing _errorStrspace numToChar _whiteSpacereturnme _cbMethod _cbObject getNetText_netID actorListaddcbObjectcbMethodurl_idList_tagList _entityListaddPropscript hasMoreTokens nextTokenchargetPropappendlengthilkinstancedeleteAt getPropRefdeleteaddAt xmlStringnewTokentextNode elementStack xmlTokenstoken currentNodenewNodeignoretypeelementnametoListprocInstcharData childListdocListnodeintegerstringindexIDtagNameelemListstrtoStringxmlDocnetDonenetError netTextResultvoiddocallwordtokenStrpiNamepiDatapiNode_docTypefindPos entityName entityValueisEmptyoffsetattributeValue attributeName getPropAtsetaPropi attributeList elementName numAttributes elementNode attributeStrtagListattrStr attrValue attrTokensattrListattrName quoteTypetokens textTokentextStrrgbredvaluegetaProp decodedStr countTokens paramCount _tokenListmin_currPos returnTokensdelims offsetListj tokenOffset numDelims delimList charOffset delimChar makeSublist attrString encodeStringtext_type_name_dataxmlListnodeList duplicatepiListtagnumAttr charToNumcharNum encodedStrnumCharscurrCharccl FmapVERS U