// shared "empty" list of children for childless objects\r
\r
list<XMLObject*> AbstractChildlessElement::m_no_children;\r
+\r
+void AbstractChildlessElement::removeChild(XMLObject* child)\r
+{\r
+ throw XMLObjectException("Cannot remove child from a childless object.");\r
+}\r
return m_no_children;\r
}\r
\r
+ void removeChild(XMLObject* child);\r
+\r
protected:\r
AbstractChildlessElement() {}\r
\r
AbstractComplexElement::~AbstractComplexElement() {
std::for_each(m_children.begin(), m_children.end(), cleanup<XMLObject>());
}
+
+void AbstractComplexElement::removeChild(XMLObject* child)
+{
+ m_children.erase(std::remove(m_children.begin(), m_children.end(), child), m_children.end());
+}
return m_children;\r
}\r
\r
+ void removeChild(XMLObject* child);\r
+\r
protected:\r
AbstractComplexElement() {}\r
\r
}\r
return NULL;\r
}\r
+\r
+void AbstractDOMCachingXMLObject::detach()\r
+{\r
+ // This is an override that duplicates some of the checking in the base class but\r
+ // adds document management in preparation for deletion of the parent.\r
+\r
+ if (!getParent())\r
+ return;\r
+\r
+ if (getParent()->hasParent())\r
+ throw XMLObjectException("Cannot detach an object whose parent is itself a child.");\r
+\r
+ AbstractDOMCachingXMLObject* parent = dynamic_cast<AbstractDOMCachingXMLObject*>(getParent());\r
+ if (parent && parent->m_document) {\r
+ // Transfer control of document to me...\r
+ setDocument(parent->m_document);\r
+ parent->m_document = NULL;\r
+ }\r
+ // The rest is done by the base.\r
+ AbstractXMLObject::detach();\r
+}\r
\r
XMLObject* clone() const;\r
\r
+ void detach();\r
+\r
protected:\r
AbstractDOMCachingXMLObject() : m_dom(NULL), m_document(NULL) {}\r
\r
\r
return newValue;\r
}\r
+\r
+void AbstractXMLObject::detach()\r
+{\r
+ if (!getParent())\r
+ return;\r
+ else if (getParent()->hasParent())\r
+ throw XMLObjectException("Cannot detach an object whose parent is itself a child.");\r
+\r
+ // Pull ourselves out of the parent and then blast him.\r
+ getParent()->removeChild(this);\r
+ delete m_parent;\r
+ m_parent = NULL;\r
+}\r
XMLString::release(&m_schemaLocation);\r
}\r
\r
+ void detach();\r
+\r
const QName& getElementQName() const {\r
return m_elementQname;\r
}\r
}\r
\r
void addNamespace(const Namespace& ns) const {\r
- if (ns.alwaysDeclare() || m_namespaces.find(ns)==m_namespaces.end()) {\r
+ std::set<Namespace>::iterator i = m_namespaces.find(ns);\r
+ if (i == m_namespaces.end())\r
m_namespaces.insert(ns);\r
- }\r
+ else if (ns.alwaysDeclare())\r
+ i->setAlwaysDeclare(true);\r
}\r
\r
void removeNamespace(const Namespace& ns) {\r
virtual XMLObject* clone() const=0;\r
\r
/**\r
+ * Specialized function for detaching a child object from its parent\r
+ * <strong>while disposing of the parent</strong>.\r
+ *\r
+ * This is not a generic way of detaching any child object, but only of\r
+ * pruning a single child from the root of an XMLObject tree. If the\r
+ * detached XMLObject's parent is itself a child, an exception will be\r
+ * thrown. It's mainly useful for turning a child into the new root of\r
+ * the tree without having to clone the child.\r
+ */\r
+ virtual void detach()=0;\r
+\r
+ /**\r
* Gets the QName for this element. This QName <strong>MUST</strong> \r
* contain the namespace URI, namespace prefix, and local element name.\r
* \r
virtual const std::list<XMLObject*>& getOrderedChildren() const=0;\r
\r
/**\r
+ * Used by a child's detach method to isolate the child from\r
+ * this parent object in preparation for destroying the parent\r
+ * (this object).\r
+ * \r
+ * @param child the child object to remove\r
+ */\r
+ virtual void removeChild(XMLObject* child)=0;\r
+\r
+ /**\r
* Gets the DOM representation of this XMLObject, if one exists.\r
* \r
* @return the DOM representation of this XMLObject\r