///////////////////////////////////////////////////////////////////// // xmlParser.cpp - parse XML elements and documents // // ver 1.2 // // Language: Visual C++, ver 7.0 // // Platform: Dell Dimension 8300, Windows XP Pro, SP1.0 // // Application: CSE687 - Object Oriented Design, Pr#3 prototype // // Author: Jim Fawcett, CST 2-187, Syracuse University // // (315) 443-3948, jfawcett@twcny.rr.com // ///////////////////////////////////////////////////////////////////// #include #include #include "xmlParser.h" ///////////////////////////////////////////////////////////////////// // class element members // //----< constructor builds tag >------------------------------------- element::element(const std::string& tag) : _tag(tag) { append("<").append(tag).append(">"); } //----< build element body >----------------------------------------- void element::body(const std::string& b) { append(b).append(""); } //----< insert string after tag >------------------------------------ void element::insert(const std::string& s) { size_t pos = find('>'); if(pos < size()) { std::string::insert(pos+1,s); } } //----< insert tag attribute >--------------------------------------- void element::attrib(const std::string& name, const std::string& value) { size_t pos = find('>'); if(pos < size()) { std::string temp = std::string(" ") + name + std::string("=\"") + value + std::string("\""); std::string::insert(pos,temp); } } // ///////////////////////////////////////////////////////////////////// // class document member // //----< constructor takes root element >----------------------------- document::document(const element& e) { append("").append(e); } ///////////////////////////////////////////////////////////////////// // class xmlParser members // //----< move to next element, equivalent to depth first search >----- size_t xmlParser::next() { while(pos < size() && ((*this)[pos]!='<' || (*this)[pos+1]=='/')) ++pos; return pos; } //----< return element >--------------------------------------------- std::string xmlParser::element() { std::string Tag = tag(); size_t last = find(Tag,pos+2); last = find('>',last) + 1; return substr(pos,last-pos); } //----< return tag >------------------------------------------------- std::string xmlParser::tag() { std::string temp; size_t i = pos + 1; while(i < size()) { char ch = (*this)[i++]; if(ch == ' ' || ch == '>') break; temp += ch; } return temp; } // //----< return element attributes collection >----------------------- xmlParser::Attributes xmlParser::attributes() { Attributes attribs; std::string name, value; size_t whereEqual = pos; size_t last = find('>',pos); while(true) { whereEqual = find('=',whereEqual + 1); if(whereEqual < last) { char ch; size_t i = whereEqual; while((ch = (*this)[i]) != ' ') { --i; if(i == 0) break; } ++i; name = substr(i,whereEqual-i); i = whereEqual + 1; value = ""; while(i < size()) { ch = (*this)[i]; if((ch == ' ' && (*this)[i-1] == '\"') || ch == '>') break; value += ch; ++i; } attribs.push_back(name,value); } else break; } return attribs; } //----< return element body >---------------------------------------- std::string xmlParser::body() { std::string Tag = tag(); size_t first = find('>',pos) + 1; std::string temp = substr(first, size()-1); if(first == size()) return ""; std::string end = std::string("/") + Tag; size_t second = temp.find(end) - 1; return substr(first,second); } // //----< move to next character in xml string >----------------------- xmlParser xmlParser::operator++(int) { xmlParser temp = *this; ++pos; return temp; } //----< move to previous character in xml string >------------------- xmlParser xmlParser::operator--(int) { xmlParser temp = *this; --pos; return temp; } //----< indenting helper function >---------------------------------- std::string indent(int level) { std::string indent = "\n"; indent += std::string(level,' '); return indent; } //----< extract text from body >------------------------------------- std::string xmlParser::text() { // not implemented yet return ""; } // //----< Test Stub >-------------------------------------------------- #ifdef TEST_XMLPARSER int main() { std::cout << "\n Testing class xmlParser " << "\n =========================\n"; std::cout << "\n Testing XML String Construction " << "\n ---------------------------------\n"; element e1("atag"); element e2("btag"); e2.attrib("attr","aValue"); e2.body("b body"); element e3("ctag"); e3.body("c body"); e1.body(e2 + e3); e1.insert("some text"); e1.attrib("attr1","someValue"); e1.attrib("attr2","another Value"); std::cout << "\n " << e1 << "\n\n"; document d(e1); std::cout << "\n " << d << "\n\n"; std::cout << "\n Testing XML String Parsing " << "\n ----------------------------\n"; xmlParser parse(d); std::string::iterator iter; size_t pos; while((pos = parse.next()) != parse.size()) { std::cout << std::endl; std::cout << " element = " << parse.element() << std::endl; std::cout << " tag = " << parse.tag() << std::endl; xmlParser::Attributes attribs = parse.attributes(); std::string name, value; while(attribs.next(name,value)) std::cout << " attrib = " << name << '=' << value << std::endl; std::cout << " body = " << parse.body() << std::endl; ++parse; } std::cout << "\n"; std::cout << "\n Testing XML Parsing with Duplicate Tags " << "\n -----------------------------------------\n"; element E1("atag"); element E2("btag"); E2.attrib("attr","aValue"); E2.body("b body"); element E3("btag"); E3.body("c body"); E1.body(E2 + E3); E1.insert("some text"); E1.attrib("attr1","someValue"); E1.attrib("attr2","another Value"); std::cout << "\n " << E1 << "\n\n"; document D(E1); std::cout << "\n " << D << "\n\n"; parse.xmlString(D); while((pos = parse.next()) != parse.size()) { std::cout << std::endl; std::cout << " element = " << parse.element() << std::endl; std::cout << " tag = " << parse.tag() << std::endl; xmlParser::Attributes attribs = parse.attributes(); std::string name, value; while(attribs.next(name,value)) std::cout << " attrib = " << name << '=' << value << std::endl; std::cout << " body = " << parse.body() << std::endl; ++parse; } std::cout << "\n"; std::cout << "\n Testing increment, head, and tail " << "\n -----------------------------------"; parse.xmlString("some body"); parse.front(); for(unsigned int i=0; i<=parse.size(); ++i) { std::cout << "\n " << parse.head(); std::cout << "\n " << parse.tail(); parse++; } std::cout << "\n\n"; } #endif