*/
#include <iostream>
+
+#include "pbd/stacktrace.h"
#include "pbd/xml++.h"
+
#include <libxml/debugXML.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
, _doc (xmlCopyDoc (from->_doc, 1))
, _compression(from->compression())
{
-
+
}
XMLTree::~XMLTree()
_doc = 0;
}
- xmlParserCtxtPtr ctxt = NULL; /* the parser context */
+ /* create a parser context */
+ xmlParserCtxtPtr ctxt = xmlNewParserCtxt();
+ if (ctxt == NULL) {
+ return false;
+ }
xmlKeepBlanksDefault(0);
/* parse the file, activating the DTD validation option */
if (validate) {
- /* create a parser context */
- ctxt = xmlNewParserCtxt();
- if (ctxt == NULL) {
- return false;
- }
_doc = xmlCtxtReadFile(ctxt, _filename.c_str(), NULL, XML_PARSE_DTDVALID);
} else {
- _doc = xmlParseFile(_filename.c_str());
+ _doc = xmlCtxtReadFile(ctxt, _filename.c_str(), NULL, XML_PARSE_HUGE);
}
-
+
/* check if parsing suceeded */
if (_doc == NULL) {
- if (validate) {
- xmlFreeParserCtxt(ctxt);
- }
+ xmlFreeParserCtxt(ctxt);
return false;
} else {
/* check if validation suceeded */
_root = readnode(xmlDocGetRootElement(_doc));
/* free up the parser context */
- if (validate) {
- xmlFreeParserCtxt(ctxt);
- }
-
+ xmlFreeParserCtxt(ctxt);
+
return true;
}
bool
-XMLTree::read_buffer(const string& buffer)
+XMLTree::read_buffer(const string& buffer, bool to_tree_doc)
{
xmlDocPtr doc;
}
_root = readnode(xmlDocGetRootElement(doc));
- xmlFreeDoc(doc);
+ if (to_tree_doc) {
+ if (_doc) {
+ xmlFreeDoc (_doc);
+ }
+ _doc = doc;
+ } else {
+ xmlFreeDoc (doc);
+ }
return true;
}
xmlSetDocCompressMode(doc, _compression);
writenode(doc, _root, doc->children, 1);
result = xmlSaveFormatFileEnc(_filename.c_str(), doc, "UTF-8", 1);
+#ifndef NDEBUG
+ if (result == -1) {
+ xmlErrorPtr xerr = xmlGetLastError ();
+ if (!xerr) {
+ std::cerr << "unknown XML error during xmlSaveFormatFileEnc()." << std::endl;
+ } else {
+ std::cerr << "xmlSaveFormatFileEnc: error"
+ << " domain: " << xerr->domain
+ << " code: " << xerr->code
+ << " msg: " << xerr->message
+ << std::endl;
+ }
+ }
+#endif
xmlFreeDoc(doc);
if (result == -1) {
return retval;
}
+static const int PROPERTY_RESERVE_COUNT = 16;
+
XMLNode::XMLNode(const string& n)
: _name(n)
, _is_content(false)
{
+ _proplist.reserve (PROPERTY_RESERVE_COUNT);
}
XMLNode::XMLNode(const string& n, const string& c)
, _is_content(true)
, _content(c)
{
+ _proplist.reserve (PROPERTY_RESERVE_COUNT);
}
XMLNode::XMLNode(const XMLNode& from)
{
+ _proplist.reserve (PROPERTY_RESERVE_COUNT);
*this = from;
}
XMLPropertyIterator curprop;
_selected_children.clear ();
- _propmap.clear ();
for (curchild = _children.begin(); curchild != _children.end(); ++curchild) {
delete *curchild;
_proplist.clear ();
}
-XMLNode&
+XMLNode&
XMLNode::operator= (const XMLNode& from)
{
- if (&from != this) {
-
- XMLPropertyList props;
- XMLPropertyIterator curprop;
- XMLNodeList nodes;
- XMLNodeIterator curnode;
-
- clear_lists ();
-
- _name = from.name();
- set_content(from.content());
-
- props = from.properties();
- for (curprop = props.begin(); curprop != props.end(); ++curprop) {
- add_property((*curprop)->name().c_str(), (*curprop)->value());
+ if (&from == this) {
+ return *this;
+ }
+
+ clear_lists ();
+
+ _name = from.name ();
+ set_content (from.content ());
+
+ const XMLPropertyList& props = from.properties ();
+
+ for (XMLPropertyConstIterator prop_iter = props.begin (); prop_iter != props.end (); ++prop_iter) {
+ set_property ((*prop_iter)->name ().c_str (), (*prop_iter)->value ());
+ }
+
+ const XMLNodeList& nodes = from.children ();
+ for (XMLNodeConstIterator child_iter = nodes.begin (); child_iter != nodes.end (); ++child_iter) {
+ add_child_copy (**child_iter);
+ }
+
+ return *this;
+}
+
+bool
+XMLNode::operator== (const XMLNode& other) const
+{
+ if (is_content () != other.is_content ()) {
+ return false;
+ }
+
+ if (is_content ()) {
+ if (content () != other.content ()) {
+ return false;
}
-
- nodes = from.children();
- for (curnode = nodes.begin(); curnode != nodes.end(); ++curnode) {
- add_child_copy(**curnode);
+ } else {
+ if (name () != other.name ()) {
+ return false;
}
}
- return *this;
+ XMLPropertyList const& other_properties = other.properties ();
+
+ if (_proplist.size () != other_properties.size ()) {
+ return false;
+ }
+
+ XMLPropertyConstIterator our_prop_iter = _proplist.begin();
+ XMLPropertyConstIterator other_prop_iter = other_properties.begin();
+
+ while (our_prop_iter != _proplist.end ()) {
+ XMLProperty const* our_prop = *our_prop_iter;
+ XMLProperty const* other_prop = *other_prop_iter;
+ if (our_prop->name () != other_prop->name () || our_prop->value () != other_prop->value ()) {
+ return false;
+ }
+ ++our_prop_iter;
+ ++other_prop_iter;
+ }
+
+ XMLNodeList const& other_children = other.children();
+
+ if (_children.size() != other_children.size()) {
+ return false;
+ }
+
+ XMLNodeConstIterator our_child_iter = _children.begin ();
+ XMLNodeConstIterator other_child_iter = other_children.begin ();
+
+ while (our_child_iter != _children.end()) {
+ XMLNode const* our_child = *our_child_iter;
+ XMLNode const* other_child = *other_child_iter;
+
+ if (*our_child != *other_child) {
+ return false;
+ }
+ ++our_child_iter;
+ ++other_child_iter;
+ }
+ return true;
+}
+
+bool
+XMLNode::operator!= (const XMLNode& other) const
+{
+ return !(*this == other);
}
const string&
} else {
ctxt = xmlXPathNewContext(_doc);
}
-
+
boost::shared_ptr<XMLSharedNodeList> result =
boost::shared_ptr<XMLSharedNodeList>(find_impl(ctxt, xpath));
-
+
xmlXPathFreeContext(ctxt);
if (doc) {
xmlFreeDoc (doc);
return add_child_copy(XMLNode (string(), c));
}
-XMLProperty*
-XMLNode::property(const char* n)
+XMLProperty const *
+XMLNode::property(const char* name) const
{
- string ns(n);
- map<string,XMLProperty*>::iterator iter;
+ XMLPropertyConstIterator iter = _proplist.begin();
- if ((iter = _propmap.find(ns)) != _propmap.end()) {
- return iter->second;
+ while (iter != _proplist.end()) {
+ if ((*iter)->name() == name) {
+ return *iter;
+ }
+ ++iter;
}
return 0;
}
-XMLProperty*
-XMLNode::property(const string& ns)
+XMLProperty const *
+XMLNode::property(const string& name) const
{
- map<string,XMLProperty*>::iterator iter;
+ XMLPropertyConstIterator iter = _proplist.begin();
- if ((iter = _propmap.find(ns)) != _propmap.end()) {
- return iter->second;
+ while (iter != _proplist.end()) {
+ if ((*iter)->name() == name) {
+ return *iter;
+ }
+ ++iter;
}
-
return 0;
}
-XMLProperty*
-XMLNode::add_property(const char* n, const string& v)
+XMLProperty *
+XMLNode::property(const char* name)
{
- string ns(n);
- map<string,XMLProperty*>::iterator iter;
-
- if ((iter = _propmap.find(ns)) != _propmap.end()) {
- iter->second->set_value (v);
- return iter->second;
+ XMLPropertyIterator iter = _proplist.begin();
+
+ while (iter != _proplist.end()) {
+ if ((*iter)->name() == name) {
+ return *iter;
+ }
+ ++iter;
}
+ return 0;
+}
- XMLProperty* tmp = new XMLProperty(ns, v);
+XMLProperty *
+XMLNode::property(const string& name)
+{
+ XMLPropertyIterator iter = _proplist.begin();
- if (!tmp) {
- return 0;
+ while (iter != _proplist.end()) {
+ if ((*iter)->name() == name) {
+ return *iter;
+ }
+ ++iter;
}
- _propmap[tmp->name()] = tmp;
- _proplist.insert(_proplist.end(), tmp);
+ return 0;
+}
- return tmp;
+bool
+XMLNode::has_property_with_value (const string& name, const string& value) const
+{
+ XMLPropertyConstIterator iter = _proplist.begin();
+
+ while (iter != _proplist.end()) {
+ if ((*iter)->name() == name && (*iter)->value() == value) {
+ return true;
+ }
+ ++iter;
+ }
+ return false;
}
-XMLProperty*
-XMLNode::add_property(const char* n, const char* v)
+bool
+XMLNode::set_property(const char* name, const string& value)
{
- string vs(v);
- return add_property(n, vs);
+ XMLPropertyIterator iter = _proplist.begin();
+
+ while (iter != _proplist.end()) {
+ if ((*iter)->name() == name) {
+ (*iter)->set_value (value);
+ return *iter;
+ }
+ ++iter;
+ }
+
+ XMLProperty* new_property = new XMLProperty(name, value);
+
+ if (!new_property) {
+ return 0;
+ }
+
+ _proplist.insert(_proplist.end(), new_property);
+
+ return new_property;
}
-XMLProperty*
-XMLNode::add_property(const char* name, const long value)
+bool
+XMLNode::get_property(const char* name, std::string& value) const
{
- char str[64];
- snprintf(str, sizeof(str), "%ld", value);
- return add_property(name, str);
+ XMLProperty const* const prop = property (name);
+ if (!prop)
+ return false;
+
+ value = prop->value ();
+
+ return true;
}
void
-XMLNode::remove_property(const string& n)
+XMLNode::remove_property(const string& name)
{
- if (_propmap.find(n) != _propmap.end()) {
- XMLProperty* p = _propmap[n];
- _proplist.remove (p);
- delete p;
- _propmap.erase(n);
+ XMLPropertyIterator iter = _proplist.begin();
+
+ while (iter != _proplist.end()) {
+ if ((*iter)->name() == name) {
+ XMLProperty* property = *iter;
+ _proplist.erase (iter);
+ delete property;
+ break;
+ }
+ ++iter;
}
}
XMLNode::remove_nodes(const string& n)
{
XMLNodeIterator i = _children.begin();
- XMLNodeIterator tmp;
-
while (i != _children.end()) {
- tmp = i;
- ++tmp;
if ((*i)->name() == n) {
- _children.erase (i);
+ i = _children.erase (i);
+ } else {
+ ++i;
}
- i = tmp;
}
}
XMLNode::remove_nodes_and_delete(const string& n)
{
XMLNodeIterator i = _children.begin();
- XMLNodeIterator tmp;
while (i != _children.end()) {
- tmp = i;
- ++tmp;
if ((*i)->name() == n) {
delete *i;
- _children.erase (i);
+ i = _children.erase (i);
+ } else {
+ ++i;
}
- i = tmp;
}
}
XMLNode::remove_nodes_and_delete(const string& propname, const string& val)
{
XMLNodeIterator i = _children.begin();
- XMLNodeIterator tmp;
- XMLProperty* prop;
+ XMLProperty const * prop;
while (i != _children.end()) {
- tmp = i;
- ++tmp;
-
prop = (*i)->property(propname);
if (prop && prop->value() == val) {
delete *i;
- _children.erase(i);
+ i = _children.erase(i);
+ } else {
+ ++i;
}
-
- i = tmp;
}
}
if (attr->children) {
content = (char*)attr->children->content;
}
- tmp->add_property((const char*)attr->name, content);
+ tmp->set_property((const char*)attr->name, content);
}
if (node->content) {
static void
writenode(xmlDocPtr doc, XMLNode* n, xmlNodePtr p, int root = 0)
{
- XMLPropertyList props;
- XMLPropertyIterator curprop;
- XMLNodeList children;
- XMLNodeIterator curchild;
xmlNodePtr node;
if (root) {
xmlNodeSetContentLen(node, (const xmlChar*)n->content().c_str(), n->content().length());
}
- props = n->properties();
- for (curprop = props.begin(); curprop != props.end(); ++curprop) {
- xmlSetProp(node, (const xmlChar*) (*curprop)->name().c_str(), (const xmlChar*) (*curprop)->value().c_str());
+ const XMLPropertyList& props = n->properties();
+
+ for (XMLPropertyConstIterator prop_iter = props.begin (); prop_iter != props.end ();
+ ++prop_iter) {
+ xmlSetProp (node, (const xmlChar*)(*prop_iter)->name ().c_str (),
+ (const xmlChar*)(*prop_iter)->value ().c_str ());
}
- children = n->children();
- for (curchild = children.begin(); curchild != children.end(); ++curchild) {
- writenode(doc, *curchild, node);
+ const XMLNodeList& children = n->children ();
+ for (XMLNodeConstIterator child_iter = children.begin (); child_iter != children.end ();
+ ++child_iter) {
+ writenode (doc, *child_iter, node);
}
}
s << " " << (*i)->name() << "=\"" << (*i)->value() << "\"";
}
s << ">\n";
-
+
for (XMLNodeList::const_iterator i = _children.begin(); i != _children.end(); ++i) {
(*i)->dump (s, p + " ");
}
-
+
s << p << "</" << _name << ">\n";
}
}