Graal Forums  

Go Back   Graal Forums > Development Forums > NPC Scripting > Code Gallery
FAQ Members List Calendar Today's Posts

Reply
 
Thread Tools Search this Thread Display Modes
  #1  
Old 08-23-2006, 11:00 AM
Tolnaftate2004 Tolnaftate2004 is offline
penguin.
Join Date: Jul 2004
Location: Berkeley, CA
Posts: 534
Tolnaftate2004 is a jewel in the roughTolnaftate2004 is a jewel in the rough
Send a message via AIM to Tolnaftate2004
XML Parser

parseXML()

Description
Here is a little code that can transform an XML file into something that GScript can understand. The format is similar to that of ActionScript's XML Object.
XML.childNodes is an array of entities within the XML object.
XML.parent is the parent entity of the XML object.
XML.nodeName is the name of entity within the XML object.
XML.nodeType is an integer representing the type of the XML object (1 for plain text, 2 for XML entity).
XML.nodeValue is the XML object / plain text nested within the XML object.
XML.attributes is a string in the pattern of var1=val1&var2=val2&...&varN=valN. Variables can also be read with XML.attributes.var.
XML.xmlDecl is the XML declaration of the XML object.
XML.docTypeDecl is the DTD of the XML object.

Except nodeType, None of these values are read only.


The Code
PHP Code:
function parseXML(strXML) {
  temp.xml = strXML;
  this.childNodes = new [0];
  temp.intOTag = temp.xml.pos("<");
  temp.intETag = temp.xml.pos(">");
  temp.intPrev = -1;
  if (temp.intOTag == -1) {
    this.childNodes.add(temp.xml);
    this.childNodes[++temp.intPrev].type = 1;
  } else {
    while (temp.intOTag > -1) {
      if (temp.intOTag > 0) {
        this.childNodes.add(temp.xml.substring(0,temp.intOTag));
        this.childNodes[++temp.intPrev].type = 1;
        this.childNodes[temp.intPrev].parent = this;
        temp.xml = temp.xml.substring(temp.intOTag);
        temp.intOTag = temp.xml.pos("<");
        temp.intETag = temp.xml.pos(">");
      }
      temp.strTag = temp.xml.substring(1,temp.intETag-1);
      temp.strTagName = temp.strTag.substring(0,temp.strTag.pos(" ")).trim();
      temp.strTag = temp.strTag.substring(temp.strTagName.length());
      this.childNodes[temp.intPrev].nodeName = temp.strTagName;
      if (!temp.strTagName.starts("?xml") && temp.strTagname != "!DOCTYPE" && !temp.strTagName.starts("!--") && !temp.strTagName.starts("!CDATA[")) {
        if (temp.strTag != " /") {
          temp.xml = temp.xml.substring(temp.intETag+1);
          temp.strXMLCopy = temp.xml;
          temp.intDepth = 1;
          do {
            temp.intOPos = temp.strXMLCopy.pos("<" @ temp.strTagName);
            temp.intEPos = temp.strXMLCopy.pos("</" @ temp.strTagName @ ">");
            if (temp.intOPos == -1) temp.intOPos = temp.strXMLCopy.length()+1;
            switch (temp.intOPos < temp.intEPos) {
              case true:
                temp.intDepth ++;
                temp.strXMLCopy = temp.strXMLCopy.substring(temp.strXMLCopy.substring(temp.intOPos+1).pos(">")+1);
                break;
              case false:
                temp.intDepth --;
                temp.strXMLCopy = temp.strXMLCopy.substring(temp.strXMLCopy.substring(temp.intEPos+1).pos(">")+1);
                break;
            }
          } while (temp.intDepth > 0);
          temp.strChild = temp.xml.substring(0,temp.intEPos);
          temp.xml = temp.xml.substring(temp.intEPos+3+temp.strTagName.length());
          this.childNodes.add("<" @ temp.strTagName @ temp.strTag @ ">" @ temp.strChild @ "</" @ temp.strTagName @ ">");
          with(this.childNodes[++temp.intPrev]) parseXML(temp.strChild);
          this.childNodes[temp.intPrev].type = 2;
          this.childNodes[temp.intPrev].nodeName = temp.strTagName;
          this.childNodes[temp.intPrev].parent = this;
          this.childNodes[temp.intPrev].nodeValue = temp.strChild;
        } else {
          this.childNodes.add("<" @ temp.strTagName @ temp.strTag @ ">");
          this.childNodes[++temp.intPrev].nodeName = temp.strTagName;
          this.childNodes[temp.intPrev].nodeType = 2;
          this.childNodes[temp.intPrev].parent = this;
          temp.xml = temp.xml.substring(temp.intETag+1);
        }
        with(this.childNodes[temp.intPrev].attributes) getAttributes(temp.strTag);
      } else {
        switch (temp.strTagName) {
          case "?xml": 
            this.xmlDecl = "<?xml" @ temp.strTag @ ">";
            with (this.xmlDecl.attributes) getAttributes(temp.strTag);
            break;
          case "
!DOCTYPE":
            this.docTypeDecl = "
<!DOCTYPE" @ temp.strTag @ ">";
            break;
        }
        if (temp.strTagName == "
!--") temp.intETag = temp.xml.pos("-->") + 2;
        elseif (temp.strTagName == "
!CDATA[") temp.intETag = temp.xml.pos("]>") + 1;
        temp.xml = temp.xml.substring(temp.intETag+1);
      }
      temp.intOTag = temp.xml.pos("
<");
      temp.intETag = temp.xml.pos("
>");
    }
    if (temp.xml.length() > 0) {
      this.childNodes.add(temp.xml);
      this.childNodes[temp.intPrev].type = 1;
      this.childNodes[temp.intPrev].parent = this;
      temp.xml = "";
    }
  }
  return strXML;
}

function getAttributes(strTag) {
  temp.arr = "";
  while(strTag.length() > 0) {
    strTag = strTag.trim();
    temp.pos = strTag.pos("
=");
    if (temp.pos > -1) {
      temp.var = strTag.substring(0,temp.pos);
      if (strTag.charat(temp.pos+1) == "
\""temp.npos strTag.substring(temp.pos+2).pos("\"");
      else 
temp.npos strTag.substring(temp.pos+2).pos(" ");
      
temp.val strTag.substring(temp.pos+2,temp.npos);
      
this.(@temp.var) = temp.val;
      
temp.arr.add(temp.var @ "=" temp.val);
      
strTag strTag.substring(temp.npos+temp.pos+3).trim();
    } else 
strTag "";
  }
  
temp.len temp.arr.size();
  
temp.str temp.arr[0];
  for (
temp.i=1;temp.i<temp.len;temp.i++)
    
temp.str @= "&" temp.arr[temp.i];
  
this temp.str;
  return;
}
Usage
with(var) this = parseXML(strXML);

Parameters
strXML A string of XML or well-formed HTML.

Returns
The parameter passed to the function.

Example
PHP Code:
function onCreated() {
  
temp.query requesturl("http://www.w3schools.com/xml/note.xml"); /* import file lines */
  
catchevent(temp.query,"onReceiveData","onData");
}

function 
onData(obj) {
  
with(methis parseXML(obj.fulldata); /* parse */
  
echo(me.xmlDecl.attributes.version); /* prints "1.0" */



The scene is set; to remake the XML file, you're going to have to get creative. Post problems / comments / etc.
__________________
◕‿‿◕ · pfa · check yer syntax! · src

Killa Be: when i got that locker in 6th grade the only thing in it was a picture of a midget useing a firehose :/

Last edited by Tolnaftate2004; 08-23-2006 at 08:47 PM..
Reply With Quote
  #2  
Old 08-23-2006, 02:31 PM
Admins Admins is offline
Graal Administration
Join Date: Jan 2000
Location: Admins
Posts: 11,693
Admins has much to be proud ofAdmins has much to be proud ofAdmins has much to be proud ofAdmins has much to be proud ofAdmins has much to be proud ofAdmins has much to be proud of
Sounds interesting and useful
A little improvement for using the requesturl object:
I think you can use "obj.fulldata" instead of merging the obj.data lines:
with(me) this = parseXML(obj.fulldata)
Reply With Quote
  #3  
Old 08-23-2006, 08:48 PM
Tolnaftate2004 Tolnaftate2004 is offline
penguin.
Join Date: Jul 2004
Location: Berkeley, CA
Posts: 534
Tolnaftate2004 is a jewel in the roughTolnaftate2004 is a jewel in the rough
Send a message via AIM to Tolnaftate2004
Thanks, I was not aware that existed.
__________________
◕‿‿◕ · pfa · check yer syntax! · src

Killa Be: when i got that locker in 6th grade the only thing in it was a picture of a midget useing a firehose :/
Reply With Quote
  #4  
Old 08-24-2006, 04:30 AM
ApothiX ApothiX is offline
Okiesmokie
Join Date: May 2004
Posts: 1,447
ApothiX is on a distinguished road
Wouldn't it work if you did it like this:
PHP Code:
me = new TStaticVar();
me parseXML(blahblah); 
?

Not sure if setting 'this' is a wise thing to do
__________________


[06:24:19] * Parts: Skyld (i=silent@unaffiliated/skyld) ("Perhaps Okiesmokie did not realise that I like the boys. ")
Reply With Quote
  #5  
Old 08-24-2006, 05:22 AM
Tolnaftate2004 Tolnaftate2004 is offline
penguin.
Join Date: Jul 2004
Location: Berkeley, CA
Posts: 534
Tolnaftate2004 is a jewel in the roughTolnaftate2004 is a jewel in the rough
Send a message via AIM to Tolnaftate2004
Quote:
Originally Posted by ApothiX
Wouldn't it work if you did it like this:
PHP Code:
me = new TStaticVar();
me parseXML(blahblah); 
?
No, parseXML just returns blahblah, so in effect I'd have just parsed some crazy string to come up with me = blahblah. It is written that way so that 'me' is given the properties stated above.

e:
PHP Code:
function parseXML(strXML) {
  ERROR = NULL;
    ERROR.NO_CLOSE_TAG = "There is no closing tag for tag <%s>.";
    ERROR.NO_CLOSE_ENT = "An entity was not terminated.";
    ERROR.XML_DECL_END = "The XML declaration was not terminated properly.";
    ERROR.COMMENT_END  = "A comment was never terminated.";
    ERROR.IMPROP_FORM  = "The XML file is improperly formed.";
  temp.xml = strXML;
  this.childNodes = new [0];
  temp.intOTag = temp.xml.pos("<");
  if (~temp.intOTag) temp.intETag = getEndIndex(temp.xml,">");
  temp.intPrev = -1;
  if (temp.intOTag == -1) {
    this.childNodes.add(temp.xml);
    this.childNodes[++temp.intPrev].nodeType = 1;
  } else {
    while (temp.intOTag > -1) {
      if (temp.intOTag > 0) {
        this.childNodes.add(temp.xml.substring(0,temp.intOTag));
        this.childNodes[++temp.intPrev].nodeType = 1;
        this.childNodes[temp.intPrev].parent = this;
        temp.xml = temp.xml.substring(temp.intOTag);
        temp.intOTag = temp.xml.pos("<");
        if (~temp.intOTag) temp.intETag = getEndIndex(temp.xml,">");
      }
      temp.strTag = temp.xml.substring(1,temp.intETag-1);
      temp.strTagName = temp.strTag.substring(0,temp.strTag.pos(" ")).trim();
      temp.strTag = temp.strTag.substring(temp.strTagName.length());
      this.childNodes[temp.intPrev].nodeName = temp.strTagName;
      if (!temp.strTagName.starts("?xml") && temp.strTagname != "!DOCTYPE" && !temp.strTagName.starts("!--") && !temp.strTagName.starts("!CDATA[")) {
        if (!temp.strTagName.starts("/")) {
          if (temp.strTag != " /") {
          temp.xml = temp.xml.substring(temp.intETag+1);
          temp.strXMLCopy = temp.xml;
          temp.intDepth = 1;
          do {
            temp.intOPos = temp.strXMLCopy.pos("<" @ temp.strTagName);
            temp.intEPos = temp.strXMLCopy.pos("</" @ temp.strTagName @ ">");
            if (temp.intOPos == -1) temp.intOPos = temp.strXMLCopy.length()+1;
            if (temp.intEPos == -1) produce_error(ERROR.NO_CLOSE_TAG,temp.strTagName);
            switch (temp.intOPos < temp.intEPos) {
              case true:
                temp.intDepth ++;
                temp.strXMLCopy = temp.strXMLCopy.substring(temp.strXMLCopy.substring(temp.intOPos+1).pos(">")+1);
                break;
              case false:
                temp.intDepth --;
                temp.strXMLCopy = temp.strXMLCopy.substring(temp.strXMLCopy.substring(temp.intEPos+1).pos(">")+1);
                break;
            }
          } while (temp.intDepth > 0);
          temp.strChild = temp.xml.substring(0,temp.intEPos);
          temp.xml = temp.xml.substring(temp.intEPos+3+temp.strTagName.length());
          this.childNodes.add("<" @ temp.strTagName @ temp.strTag @ ">" @ temp.strChild @ "</" @ temp.strTagName @ ">");
          with(this.childNodes[++temp.intPrev]) parseXML(temp.strChild);
          this.childNodes[temp.intPrev].nodeType = 2;
          this.childNodes[temp.intPrev].nodeName = temp.strTagName;
          this.childNodes[temp.intPrev].parent = this;
          this.childNodes[temp.intPrev].nodeValue = temp.strChild;
        } else {
          this.childNodes.add("<" @ temp.strTagName @ temp.strTag @ ">");
          this.childNodes[++temp.intPrev].nodeName = temp.strTagName;
          this.childNodes[temp.intPrev].nodeType = 2;
          this.childNodes[temp.intPrev].parent = this;
          temp.xml = temp.xml.substring(temp.intETag+1);
        }
        with(this.childNodes[temp.intPrev].attributes) getAttributes(temp.strTag);
        } else produce_error(ERROR.IMPROP_FORM);
      } else {
        switch (temp.strTagName) {
          case "?xml":
            temp.intETag = temp.xml.pos("?>");
            if (intETag == -1) produce_error(ERROR.XML_DECL_END);
            temp.strTag = temp.xml.substring(5,temp.intETag-5);
            this.xmlDecl = "<?xml" @ temp.strTag @ "?>";
            with (this.xmlDecl.attributes) getAttributes(temp.strTag);
            break;
          case "!DOCTYPE":
            this.docTypeDecl = "<!DOCTYPE" @ temp.strTag @ ">";
            break;
        }
        if (temp.strTagName == "!--") {
          temp.pos = temp.xml.pos("-->");
          if (temp.pos > -1) temp.intETag = temp.pos + 2;
          else produce_error(ERROR.COMMENT_END);
        }
        elseif (temp.strTagName == "!CDATA[") {
          temp.pos = temp.xml.pos("]>");
          if (temp.pos > -1) temp.intETag = temp.pos + 1;
          else produce_error(ERROR.COMMENT_END);
        }
        temp.xml = temp.xml.substring(temp.intETag+1);
      }
      temp.intOTag = temp.xml.pos("<");
      if (~temp.intOTag) temp.intETag = getEndIndex(temp.xml,">");
    }
    if (temp.xml.length() > 0) {
      this.childNodes.add(temp.xml);
      this.childNodes[temp.intPrev].nodeType = 1;
      this.childNodes[temp.intPrev].parent = this;
      temp.xml = "";
    }
  }
  return strXML;
}

function getAttributes(strTag) {
  temp.arr = "";
  while(strTag.length() > 0) {
    strTag = strTag.trim();
    temp.pos = strTag.pos("=");
    if (temp.pos > -1) {
      temp.var = strTag.substring(0,temp.pos);
      if (strTag.charat(temp.pos+1) == char(34)) {
        temp.npos = strTag.substring(temp.pos+2).pos(char(34) @ " ");
        temp.len = strTag.substring(temp.pos+2).length();
        if (temp.npos == -1 && strTag.substring(temp.pos+2).substring(temp.len-1,1) == char(34)) temp.npos = temp.len-1;
      }
      else temp.npos = strTag.substring(temp.pos+2).pos(" ");
      temp.val = strTag.substring(temp.pos+2,temp.npos);
      this.(@temp.var) = temp.val;
      temp.arr.add(temp.var @ "=" @ temp.val);
      strTag = strTag.substring(temp.npos+temp.pos+3).trim();
    } else strTag = "";
  }
  temp.len = temp.arr.size();
  temp.str = temp.arr[0];
  for (temp.i=1;temp.i<temp.len;temp.i++)
    temp.str @= "&" @ temp.arr[temp.i];
  this = temp.str;
  return;
}

function getEndIndex(strXML,endtag) {
  temp.olen = 0;
  while (1) { // We'll return directly from inside
    temp.test = strXML.pos(endtag);
    if (temp.test == -1) {
      produce_error(ERROR.NO_CLOSE_ENT);
      return -1;
    }
    temp.before = strXML.substring(temp.test);
    temp.open = 0;
    do {
      temp.pos = temp.before.pos("=\"");
      if (temp.pos > -1) {
        temp.before = temp.before.substring(temp.pos+2);
        temp.open = 1;
        temp.pos = temp.before.pos("\" ");
        if (temp.pos > -1) {
          temp.before = temp.before.substring(temp.pos+2);
          temp.open = 0;
        } elseif (temp.before.substring(temp.before.length()-1,1) == "\"") {
          // \"
          temp.before = "";
          temp.open = 0;
        }
      }
    } while(temp.pos > -1 && temp.open == 0);
    if (temp.open == 1) {
      strXML = strXML.substring(temp.test+endtag.length());
      temp.olen += temp.test+endtag.length();
    } else return temp.olen + temp.test;
  }
  return -1; // 1 != true ?
}

function produce_error(strError) {
  echo(format(strError,params.subarray(1)));
  return;
}
Some bug fixes:
  • The xml declaration looks for the '?>' closing tag.
  • Quotes next to the closing tag are removed.
  • attributes can contain '>' now.

Some additions:
  • Error messages.
  • XML.nodeType now works for all nodes (I had originally scripted it to be XML.type and some of the .type code was still there. They were also never read-only at all, it seems.
__________________
◕‿‿◕ · pfa · check yer syntax! · src

Killa Be: when i got that locker in 6th grade the only thing in it was a picture of a midget useing a firehose :/

Last edited by Tolnaftate2004; 08-24-2006 at 08:47 PM..
Reply With Quote
  #6  
Old 08-25-2006, 10:40 AM
ApothiX ApothiX is offline
Okiesmokie
Join Date: May 2004
Posts: 1,447
ApothiX is on a distinguished road
Ah, I see what it's doing now, but I still stand by my saying I don't think you should be setting this, especially if you're just setting it as a string. Why not just make it set a 'me.parsedXML', and return an error code?

PHP Code:
with(me) {
  
temp.errorcode parseXML();
}

switch(
temp.errorcode) {
// Error Checking

__________________


[06:24:19] * Parts: Skyld (i=silent@unaffiliated/skyld) ("Perhaps Okiesmokie did not realise that I like the boys. ")
Reply With Quote
  #7  
Old 08-25-2006, 07:45 PM
Tolnaftate2004 Tolnaftate2004 is offline
penguin.
Join Date: Jul 2004
Location: Berkeley, CA
Posts: 534
Tolnaftate2004 is a jewel in the roughTolnaftate2004 is a jewel in the rough
Send a message via AIM to Tolnaftate2004
Quote:
Originally Posted by ApothiX
Ah, I see what it's doing now, but I still stand by my saying I don't think you should be setting this, especially if you're just setting it as a string.
Because the way I have it is the only way I could figure out the recursion to work correctly. If I set the string inside of the function, any child that has children will be changed to that child's children. If you get what I'm saying.

PHP Code:
<key />
<
node id="1">
  <
childnode />
</
node
'me' would still be '<key />\n<node id="1">\n <childnode />\n</node>', but 'me.childNodes' would come up with <key /> and ' ,<childnode />'.
Yes, it is possible to change that, but it would be reparsing bits that have already been parsed.

And setting this is not harming anything. I am merely setting a variable a different way.

PHP Code:
new TGraalVar("me") {
  
this "This is perfectly acceptable.";

If I was setting the NPC's this, then it might be a problem.

Quote:
Originally Posted by ApothiX
Why not just make it set a 'me.parsedXML', and return an error code?

PHP Code:
with(me) {
  
temp.errorcode parseXML();
}

switch(
temp.errorcode) {
// Error Checking

Well, if I really wanted to follow ActionScript, I would set XML.status, which gives an error code.

e:
temp.before = strXML.substring(temp.test);
should be
temp.before = strXML.substring(0,temp.test);
in the code.
__________________
◕‿‿◕ · pfa · check yer syntax! · src

Killa Be: when i got that locker in 6th grade the only thing in it was a picture of a midget useing a firehose :/

Last edited by Tolnaftate2004; 08-26-2006 at 01:45 AM..
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 03:46 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Copyright (C) 1998-2019 Toonslab All Rights Reserved.