/* DOM implementation */ #include #include #include #include using namespace std; /* Currently using Element for all nodes and going by the nodeName to determine the type of node */ struct Element { string nodeName; string nodeValue; vector childNodes; map attributes; void appendChild( Element e ) { Element::childNodes.push_back( e ); } vector getElementsByTagName(const string& tag ) { /* doesn't support space-separated or '*' yet */ /* Also doesn't recurse through nodes yet */ vector temp; for ( size_t i = 0; i < Element::childNodes.size(); ++i ) { if ( Element::childNodes[i].nodeName == tag ) { temp.push_back( &Element::childNodes[i] ); } } return temp; } bool hasChildNodes() const { if ( !Element::childNodes.empty() ) { return true; } return false; } void setAttribute( const string& name, const string& value ) { attributes[ name ] = value; } string getAttribute( const string& name ) { return attributes[name]; } string getOuterHTML() const { string temp; temp += "<"; temp += Element::nodeName; if ( Element::nodeName != "#text") { for ( map::const_iterator i = Element::attributes.begin(); i != Element::attributes.end(); ++i ) { temp += " "; temp += i->first; temp += "=\""; temp += i->second; temp += "\""; } } temp += ">"; if ( Element::hasChildNodes() ) { for ( size_t i = 0; i < childNodes.size(); ++i ) { if ( childNodes[i].nodeName != "#text" ) { temp += childNodes[i].getOuterHTML(); } else { temp += childNodes[i].nodeValue; } } temp += ""; } return temp; } string getInnerHTML() const { if ( Element::hasChildNodes() ) { return Element::childNodes[0].getOuterHTML(); } return ""; } }; struct Document : public Element { Element* documentElement; Element* body; Element createElement(const string& tag) const { Element temp; temp.nodeName = tag; return temp; } Element createTextNode( const string& text ) const { Element temp; temp.nodeValue = text; temp.nodeName = "#text"; return temp; } } document; struct Window { Document* document; template void alert( const T& s ) const { cout << s << endl; } } window; #define alert window.alert /* making alert() global */ typedef Element TextNode; /* used to store a text node */ typedef vector ElementPtrArray; /* used to store pointers to elements found by getElementsByTagName() */ typedef Element* ElementPtr; /* use to store a pointer to an element */ int main() { /* Give the document a nodeName and append the first ( root ) element */ document.nodeName = "#document"; document.appendChild( document.createElement("html") ); /* document.documentElement is a pointer to the root element, which in this case, is html */ document.documentElement = document.getElementsByTagName("html")[0]; /* Now that the document has a root element, append stuff to the root element using the documentElement pointer */ document.documentElement->setAttribute("lang", "en"); document.documentElement->appendChild( document.createElement("head") ); document.documentElement->appendChild( document.createElement("body") ); /* document.body is a pointer to the first body element in the root element */ document.body = document.documentElement->getElementsByTagName("body")[0]; /* For the next 2 lines, add a title element to the head and add its text node, but do it without creating any new element instances in main just to test. */ document.documentElement->getElementsByTagName("head")[0]->appendChild( document.createElement("title") ); document.documentElement->getElementsByTagName("head")[0]->getElementsByTagName("title")[0]->appendChild( document.createTextNode("c++ dom") ); /* window.document is just a pointer to document. */ window.document = &document; /* Element itself defines a new element, in which a .nodeName could be set, but doing it with document.createElement to be JS-like and because the nodeName is set automatically. */ Element p = document.createElement("p"); p.setAttribute("id", "blabla"); p.appendChild( document.createTextNode("This is a paragraph") ); document.body->appendChild( p ); alert( document.getInnerHTML() ); alert( document.documentElement->getOuterHTML() ); alert( document.body->getInnerHTML() ); alert( document.body->getOuterHTML() ); }