<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>.simplicity &#187; SXML Parser</title>
	<atom:link href="http://www.dotsimplicity.net/tag/sxml-parser/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.dotsimplicity.net</link>
	<description>Simple, reliable, simplicity. A software discussion blog</description>
	<lastBuildDate>Sun, 04 Jul 2010 09:44:42 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>SXML Parser</title>
		<link>http://www.dotsimplicity.net/2009/02/sxml-parser/</link>
		<comments>http://www.dotsimplicity.net/2009/02/sxml-parser/#comments</comments>
		<pubDate>Tue, 03 Feb 2009 16:41:49 +0000</pubDate>
		<dc:creator>Nick</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Software Idea]]></category>
		<category><![CDATA[SXML]]></category>
		<category><![CDATA[SXML Parser]]></category>

		<guid isPermaLink="false">http://www.dotsimplicity.net/?p=106</guid>
		<description><![CDATA[Oi, it&#8217;s done I guess. Beta phase though, but it seems to work rather well! This code parses the &#8220;SXML&#8221; of the post right before this one.
It&#8217;s tested with this file:
&#60;window 100 456 789 120 windone SimpleXML&#62;
  &#60;button 101 258 369 123 buttone Ok 1337/&#62;
  &#60;button 102 258 369 123 buttwo Cancel 1338/&#62;
&#60;/&#62;

&#60;window [...]]]></description>
			<content:encoded><![CDATA[<p>Oi, it&#8217;s done I guess. Beta phase though, but it seems to work rather well! This code parses the &#8220;SXML&#8221; of the post right before this one.</p>
<p>It&#8217;s tested with this file:</p>
<pre>&lt;window 100 456 789 120 windone SimpleXML&gt;
  &lt;button 101 258 369 123 buttone Ok 1337/&gt;
  &lt;button 102 258 369 123 buttwo Cancel 1338/&gt;
&lt;/&gt;

&lt;window 103 456 789 120 windtwo SimpleXML1&gt;
  &lt;window 104 456 789 120 windthree SimpleXML2&gt;
    &lt;button 105 258 369 123 buttwo yes 1339/&gt;
    &lt;button 106 258 369 123 buttwo nay 1340/&gt;
  &lt;/&gt;
  &lt;button 106 258 369 123 buttwo nay 1340/&gt;
&lt;/&gt;</pre>
<p><span id="more-106"></span></p>
<pre class="brush: cpp;">
/*Free to do anything (with this source file) but leave this comment block alone!
  Created by .simplicity's Nick Overdijk (nick@dotsimplicity.net)
*/
#include &lt;iostream&gt;
#include &lt;cstdio&gt;
#include &lt;fstream&gt;
#include &lt;string&gt;
#include &lt;sstream&gt;
#include &lt;vector&gt;
#include &lt;stack&gt;
using namespace std;

/*Load file into memory as string
  create vector of element pointers
  parse the document, create elements on the fly
*/

class element {
public:
    element();

    element(string &amp;amp;amp;amp;amp;type, unsigned int x, unsigned int y, unsigned int height, unsigned int width, element *parent) :
    type(type), x(x), y(y), height(height), width(width), parent(parent) {
    }

    element(string &amp;amp;amp;amp;amp;attributes) :
    attributes(attributes) {
        attributeStream.str(attributes);
        parse();
    }

    virtual ~element(){ cout &lt;&lt; &quot;Finishing element&quot; &lt;&lt; endl; }

    virtual void printInfo() {
        cout &lt;&lt; &quot;---&quot; &lt;&lt; type &lt;&lt; &quot; @ &quot; &lt;&lt; this &lt;&lt; &quot;---&quot; &lt;&lt; endl;
        cout &lt;&lt; &quot;Width: &quot; &lt;&lt; width &lt;&lt; endl;
        cout &lt;&lt; &quot;Height: &quot; &lt;&lt; height &lt;&lt; endl;
        cout &lt;&lt; &quot;x: &quot; &lt;&lt; x &lt;&lt; endl;
        cout &lt;&lt; &quot;y: &quot; &lt;&lt; y &lt;&lt; endl;
        if(parent != NULL)
        cout &lt;&lt; &quot;Parent: &quot; &lt;&lt; parent &lt;&lt; &quot;(&quot; &lt;&lt; parent-&gt;type &lt;&lt; &quot;::&quot; &lt;&lt; parent-&gt;name &lt;&lt; &quot;)&quot; &lt;&lt; endl;
    }

    void printTree() {
        printInfo();
        if (parent != NULL) {
            parent-&gt;printTree();
        }
    }

    virtual void parse(){
        attributeStream &gt;&gt; type;
        attributeStream &gt;&gt; x;
        attributeStream &gt;&gt; y;
        attributeStream &gt;&gt; width;
        attributeStream &gt;&gt; height;
    }

    void setParent(element *parent){
        this-&gt;parent = parent;
    }

    string name;
    string type;
    string attributes;
    stringstream attributeStream;
    unsigned int x;
    unsigned int y;
    unsigned int height;
    unsigned int width;
    element *parent;
};

class button : public element {
    public:
    button(string &amp;amp;amp;amp;amp;attributes) :
    element(attributes) {
        parse();
    }

    virtual ~button() { cout &lt;&lt; endl; }

    virtual void parse(){
        attributeStream &gt;&gt; name;
        attributeStream &gt;&gt; caption;
        attributeStream &gt;&gt; style;
    }

    virtual void printInfo(){
        element::printInfo();
        cout &lt;&lt; &quot;Name: &quot; &lt;&lt; name &lt;&lt; endl;
        cout &lt;&lt; &quot;Caption: &quot; &lt;&lt; caption &lt;&lt; endl;
        cout &lt;&lt; &quot;Style: &quot; &lt;&lt; style &lt;&lt; endl;
    }

    string caption;
    int style;
};

class window : public element {
    public:
    window(string &amp;amp;amp;amp;amp;attributes) :
    element(attributes) {
        parse();
    }

    virtual ~window() { cout &lt;&lt; endl; }

    virtual void parse(){
        attributeStream &gt;&gt; name;
        attributeStream &gt;&gt; title;
    }

    virtual void printInfo(){
        element::printInfo();
        cout &lt;&lt; &quot;Name: &quot; &lt;&lt; name &lt;&lt; endl;
        cout &lt;&lt; &quot;Title: &quot; &lt;&lt; title &lt;&lt; endl;
    }

    string title;
};

element *createElement(string &amp;amp;amp;amp;amp;type, string &amp;amp;amp;amp;amp;attributes){
#define \
createThis(x)\
if(type == #x) return new x(attributes)

    createThis(button);
    else createThis(window);
    else return NULL;
}

/*Each part of the code is divided into:
   Letting the user know what we're doing
   Do it
   Perform a check
   Tell the user fail or done
   exit or continue
  At any given time, the user knows what the program is doing and it helps debugging a lot.
*/

int main(int argc, char *argv[]) {
    vector&lt;element*&gt; elementList;

    cout &lt;&lt; &quot;Opening file: &quot;;
    ifstream document;
    document.open(&quot;test.sxml&quot;, ios::binary);
    if (!document.is_open()) {
        cout &lt;&lt; &quot;[fail]&quot; &lt;&lt; endl;
        exit(-1);
    } else {
        cout &lt;&lt; &quot;[done]&quot; &lt;&lt; endl;
    }

    cout &lt;&lt; &quot;Getting filesize: &quot;;
    document.seekg(0, ios::end);
    unsigned int docLen = document.tellg();
    document.seekg(0, ios::beg);
    cout &lt;&lt; docLen &lt;&lt; &quot; bytes. [done]&quot; &lt;&lt; endl;

    cout &lt;&lt; &quot;Loading file into memory: &quot;;

    char *buf = new char [docLen];
    document.read(buf, docLen);
    if (document.bad()) {
        cout &lt;&lt; &quot;[fail]&quot; &lt;&lt; endl;
    } else {
        cout &lt;&lt; &quot;[done]&quot; &lt;&lt; endl;
    }

    cout &lt;&lt; &quot;Parsing file for elements: &quot;;
    /*Algorithm:
          Find a '&lt;'
          if nextchar != '/''
              read in data until &gt;
              parse data, create element
              if char before &gt; != '/'
                  push this element as curent parent
          else if nextchar == '/'
              pop the last parent
    */

    stack &lt;element*&gt; parentStack;
    parentStack.push(NULL);
    unsigned int n, i;
    for (i = 0; i &lt; docLen; i++) {
        if (buf[i] == '&lt;') {
            if (buf[i+1] != '/') {
                for(n = i+1; buf[n] != '&gt;' &amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp; buf[n] != '/'; n++);
                unsigned int lineLength = n - i;
                string line(&amp;amp;amp;amp;amp;buf[i+1], lineLength-1);
                //cout &lt;&lt; &quot;DEBUG LINE READ: &quot; &lt;&lt; line &lt;&lt; endl;
                stringstream lineStream(line);
                string type;
                lineStream &gt;&gt; type;
                element *curElem = createElement(type, line);
                curElem-&gt;setParent(parentStack.top());

                for (n = i+2; buf[n] != '&gt;'; n++);
                if (buf[n-1] != '/') {
                    parentStack.push(curElem);
                }
                elementList.push_back(curElem);
            } else {
                parentStack.pop();
            }
        }
    }
    cout &lt;&lt; &quot;[done]&quot; &lt;&lt; endl;

    for (unsigned int n = 0; n &lt; elementList.size(); n++) {
        elementList[n]-&gt;printInfo();
    }
    return 0;
}
</pre>
<p>Sooo, feel free to comment on the code, but make it useful.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dotsimplicity.net/2009/02/sxml-parser/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

