diff options
| author | Carl Hetherington <cth@carlh.net> | 2014-10-09 13:42:36 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2014-10-09 13:42:36 +0100 |
| commit | fd7dada1f4f5668e56a7cf3a268d22702f6ba52d (patch) | |
| tree | dabaa446843c772fb0a3ec92091fe11b595f29ab /src/cxml.cc | |
| parent | 01edbdf34b0ad804106e184bd98b7d20c8f23cf1 (diff) | |
Don't use xmlpp as the data storage; put things in cxml::Node members
instead. Add short-cuts for creating XML using libcxml.
Diffstat (limited to 'src/cxml.cc')
| -rw-r--r-- | src/cxml.cc | 221 |
1 files changed, 135 insertions, 86 deletions
diff --git a/src/cxml.cc b/src/cxml.cc index 810abf8..9a6a4e1 100644 --- a/src/cxml.cc +++ b/src/cxml.cc @@ -24,70 +24,107 @@ #include <libxml++/libxml++.h> #include "cxml.h" -using namespace std; -using namespace boost; +using std::pair; +using std::list; +using std::istream; +using std::string; +using std::make_pair; +using std::map; +using std::stringstream; +using boost::shared_ptr; +using boost::optional; cxml::Node::Node () - : _node (0) { } -cxml::Node::Node (xmlpp::Node* node) - : _node (node) +cxml::Node::Node (xmlpp::Node const * node) { + read (node); +} +void +cxml::Node::read (xmlpp::Node const * node) +{ + _name = node->get_name (); + _namespace_uri = node->get_namespace_uri (); + _namespace_prefix = node->get_namespace_prefix (); + + xmlpp::Node::NodeList content = node->get_children (); + for (xmlpp::Node::NodeList::const_iterator i = content.begin(); i != content.end(); ++i) { + xmlpp::ContentNode const * v = dynamic_cast<xmlpp::ContentNode const *> (*i); + if (v) { + _content += v->get_content (); + } else { + _children.push_back (cxml::NodePtr (new cxml::Node (*i))); + } + } + + xmlpp::Element const * element = dynamic_cast<xmlpp::Element const *> (node); + if (element) { + xmlpp::Element::AttributeList attributes = element->get_attributes (); + for (list<xmlpp::Attribute*>::const_iterator i = attributes.begin(); i != attributes.end(); ++i) { + _attributes.push_back (make_pair ((*i)->get_name(), (*i)->get_value ())); + } + } } -string -cxml::Node::name () const +void +cxml::Node::write (xmlpp::Node* parent) const { - assert (_node); - return _node->get_name (); + xmlpp::Element* node = parent->add_child (_name); + + if (!_content.empty ()) { + node->add_child_text (_content); + } + + for (list<pair<string, string> >::const_iterator i = _attributes.begin(); i != _attributes.end(); ++i) { + node->set_attribute (i->first, i->second); + } + + for (NodeList::const_iterator i = _children.begin(); i != _children.end(); ++i) { + (*i)->write (node); + } } -shared_ptr<cxml::Node> +cxml::NodePtr cxml::Node::node_child (string name) const { - list<shared_ptr<cxml::Node> > n = node_children (name); + NodeList n = node_children (name); if (n.size() > 1) { throw cxml::Error ("duplicate XML tag " + name); } else if (n.empty ()) { - throw cxml::Error ("missing XML tag " + name + " in " + _node->get_name()); + throw cxml::Error ("missing XML tag " + name + " in " + _name); } return n.front (); } -shared_ptr<cxml::Node> +cxml::NodePtr cxml::Node::optional_node_child (string name) const { - list<shared_ptr<cxml::Node> > n = node_children (name); + NodeList n = node_children (name); if (n.size() > 1) { throw cxml::Error ("duplicate XML tag " + name); } else if (n.empty ()) { - return shared_ptr<cxml::Node> (); + return NodePtr (); } return n.front (); } -list<shared_ptr<cxml::Node> > +cxml::NodeList cxml::Node::node_children (string name) const { - /* XXX: using find / get_path should work here, but I can't follow - how get_path works. - */ - - xmlpp::Node::NodeList c = _node->get_children (); + NodeList n; - list<shared_ptr<cxml::Node> > n; - for (xmlpp::Node::NodeList::iterator i = c.begin (); i != c.end(); ++i) { - if ((*i)->get_name() == name) { - n.push_back (shared_ptr<Node> (new Node (*i))); + for (NodeList::const_iterator i = _children.begin(); i != _children.end(); ++i) { + if ((*i)->name() == name) { + n.push_back (*i); } } - + _taken.push_back (name); return n; } @@ -101,7 +138,7 @@ cxml::Node::string_child (string c) const optional<string> cxml::Node::optional_string_child (string c) const { - list<shared_ptr<Node> > nodes = node_children (c); + NodeList nodes = node_children (c); if (nodes.size() > 1) { throw cxml::Error ("duplicate XML tag " + c); } @@ -140,33 +177,31 @@ cxml::Node::ignore_child (string name) const string cxml::Node::string_attribute (string name) const { - xmlpp::Element const * e = dynamic_cast<const xmlpp::Element *> (_node); - if (!e) { - throw cxml::Error ("missing attribute"); + list<pair<string, string> >::const_iterator i; + while (i != _attributes.end() && i->first != name) { + ++i; } - xmlpp::Attribute* a = e->get_attribute (name); - if (!a) { + if (i == _attributes.end ()) { throw cxml::Error ("missing attribute"); } - return a->get_value (); + return i->second; } optional<string> cxml::Node::optional_string_attribute (string name) const { - xmlpp::Element const * e = dynamic_cast<const xmlpp::Element *> (_node); - if (!e) { - return optional<string> (); + list<pair<string, string> >::const_iterator i; + while (i != _attributes.end() && i->first != name) { + ++i; } - xmlpp::Attribute* a = e->get_attribute (name); - if (!a) { + if (i == _attributes.end ()) { return optional<string> (); } - return string (a->get_value ()); + return i->second; } bool @@ -190,10 +225,9 @@ cxml::Node::optional_bool_attribute (string name) const void cxml::Node::done () const { - xmlpp::Node::NodeList c = _node->get_children (); - for (xmlpp::Node::NodeList::iterator i = c.begin(); i != c.end(); ++i) { - if (dynamic_cast<xmlpp::Element *> (*i) && find (_taken.begin(), _taken.end(), (*i)->get_name()) == _taken.end ()) { - throw cxml::Error ("unexpected XML node " + (*i)->get_name()); + for (NodeList::const_iterator i = _children.begin(); i != _children.end(); ++i) { + if (find (_taken.begin(), _taken.end(), (*i)->name()) == _taken.end ()) { + throw cxml::Error ("unexpected XML node " + (*i)->name()); } } } @@ -201,92 +235,107 @@ cxml::Node::done () const string cxml::Node::content () const { - string content; - - xmlpp::Node::NodeList c = _node->get_children (); - for (xmlpp::Node::NodeList::const_iterator i = c.begin(); i != c.end(); ++i) { - xmlpp::ContentNode const * v = dynamic_cast<xmlpp::ContentNode const *> (*i); - if (v) { - content += v->get_content (); - } - } - - return content; + return _content; } string cxml::Node::namespace_uri () const { - return _node->get_namespace_uri (); + return _namespace_uri; } string cxml::Node::namespace_prefix () const { - return _node->get_namespace_prefix (); + return _namespace_prefix; } -cxml::Document::Document (string root_name) - : _root_name (root_name) +void +cxml::Node::set_string_content (string c) { - _parser = new xmlpp::DomParser; + _content = c; } -cxml::Document::Document (string root_name, boost::filesystem::path file) - : _root_name (root_name) +void +cxml::Node::set_bool_content (bool c) { - _parser = new xmlpp::DomParser (); - read_file (file); + _content = c ? "yes" : "no"; } -cxml::Document::Document () +cxml::NodePtr +cxml::Node::add_string (string name, string content) { - _parser = new xmlpp::DomParser (); + NodePtr n = add (name); + n->set_string_content (content); + return n; } - -cxml::Document::~Document () + +cxml::NodePtr +cxml::Node::add_bool (std::string name, bool content) { - delete _parser; + NodePtr n = add (name); + n->set_bool_content (content); + return n; } void -cxml::Document::read_file (filesystem::path file) +cxml::Document::read_file (boost::filesystem::path file) { - if (!filesystem::exists (file)) { + if (!boost::filesystem::exists (file)) { throw cxml::Error ("XML file does not exist"); } - - _parser->parse_file (file.string ()); - take_root_node (); + + xmlpp::DomParser parser; + parser.parse_file (file.string ()); + read (parser.get_document()->get_root_node ()); } void cxml::Document::read_stream (istream& stream) { - _parser->parse_stream (stream); - take_root_node (); + xmlpp::DomParser parser; + parser.parse_stream (stream); + read (parser.get_document()->get_root_node ()); } void cxml::Document::read_string (string s) { + xmlpp::DomParser parser; stringstream t (s); - _parser->parse_stream (t); - take_root_node (); + parser.parse_stream (t); + read (parser.get_document()->get_root_node ()); } void -cxml::Document::take_root_node () +cxml::Document::check_root_name (string r) { - if (!_parser) { - throw cxml::Error ("could not parse XML"); - } - - _node = _parser->get_document()->get_root_node (); - if (!_root_name.empty() && _node->get_name() != _root_name) { + if (name() != r) { throw cxml::Error ("unrecognised root node"); - } else if (_root_name.empty ()) { - _root_name = _node->get_name (); } } +void +cxml::Document::write_to_file_formatted (boost::filesystem::path path) const +{ + xmlpp::Document doc; + write_to_xmlpp_document (doc); + doc.write_to_file_formatted (path.string ()); +} + +void +cxml::Document::write_to_string (std::string coding) const +{ + xmlpp::Document doc; + write_to_xmlpp_document (doc); + doc.write_to_string (coding); +} + +void +cxml::Document::write_to_xmlpp_document (xmlpp::Document& doc) const +{ + xmlpp::Element* root = doc.create_root_node (name ()); + for (NodeList::const_iterator i = _children.begin(); i != _children.end(); ++i) { + (*i)->write (root); + } +} |
