diff --git a/libs/yxml/XML.cpp b/libs/yxml/XML.cpp index ba34974b..2e865d1f 100644 --- a/libs/yxml/XML.cpp +++ b/libs/yxml/XML.cpp @@ -1533,10 +1533,8 @@ XmlSaxParser::Error XmlDocument::addChild(XmlChild* child) // Text outside root: ignore empty, raise error otherwise XmlText* text = child->xmlText(); if (text) { - String tmp(text->getText()); - tmp.trimSpaces(); - if (!tmp) { - TelEngine::destruct(child); + if (text->onlySpaces()) { + m_beforeRoot.addChild(text); return XmlSaxParser::NoError; } Debug(DebugNote,"XmlDocument. Got text outside element [%p]",this); @@ -1551,6 +1549,8 @@ XmlSaxParser::Error XmlDocument::addChild(XmlChild* child) DDebug(DebugStub,"XmlDocument. Request to add xml element child to incomplete root [%p]",this); return XmlSaxParser::NotWellFormed; } + if ((child->xmlText() && child->xmlText()->onlySpaces()) || child->xmlComment()) + return m_afterRoot.addChild(child); // TODO: check what xml we can add after the root or if we can add // anything after an incomplete root Debug(DebugStub,"XmlDocument. Request to add non element while having a root [%p]",this); @@ -1581,6 +1581,7 @@ void XmlDocument::toString(String& dump, bool escape, const String& indent, cons dump << origIndent; m_root->toString(dump,escape,indent,origIndent); } + m_afterRoot.toString(dump,escape,indent,origIndent); } // Reset this XmlDocument. Destroys root and clear the others xml objects @@ -1588,6 +1589,7 @@ void XmlDocument::reset() { TelEngine::destruct(m_root); m_beforeRoot.clearChildren(); + m_afterRoot.clearChildren(); m_file.clear(); } @@ -1606,6 +1608,7 @@ XmlSaxParser::Error XmlDocument::read(Stream& in, int* error) } break; } + parser.completeText(); if (parser.error() != XmlSaxParser::NoError) { DDebug(DebugNote,"XmlDocument error loading stream. Parser error %d '%s' [%p]", parser.error(),parser.getError(),this); @@ -1633,6 +1636,7 @@ int XmlDocument::write(Stream& out, bool escape, const String& indent, m_beforeRoot.toString(dump,escape,indent,origIndent); if (m_root) m_root->toString(dump,escape,indent,origIndent,completeOnly); + m_afterRoot.toString(dump,escape,indent,origIndent); return out.writeData(dump); } @@ -1813,6 +1817,13 @@ const String& XmlElement::getText() return txt ? txt->getText() : String::empty(); } +XmlChild* XmlElement::getFirstChild() +{ + if (!m_children.getChildren().skipNull()) + return 0; + return static_cast(m_children.getChildren().skipNull()->get()); +} + // Add a text child void XmlElement::addText(const char* text) { @@ -2169,6 +2180,19 @@ void XmlText::toString(String& dump, bool esc, const String& indent, dump << m_text; } +bool XmlText::onlySpaces() +{ + if (!m_text) + return true; + const char *s = m_text; + unsigned int i = 0; + for (;i < m_text.length();i++) { + if (s[i] == ' ' || s[i] == '\t' || s[i] == '\v' || s[i] == '\f' || s[i] == '\r' || s[i] == '\n') + continue; + return false; + } + return true; +} /* * XmlDoctype diff --git a/libs/yxml/yatexml.h b/libs/yxml/yatexml.h index 20cae0d3..c6559dfa 100644 --- a/libs/yxml/yatexml.h +++ b/libs/yxml/yatexml.h @@ -1085,6 +1085,7 @@ private: XmlElement* m_root; // The root element XmlFragment m_beforeRoot; // XML children before root (declaration ...) String m_file; // The file name used on load + XmlFragment m_afterRoot; // XML children after root (comments, empty text) }; @@ -1312,7 +1313,7 @@ public: const String* auth = 0) const; /** - * Find the first child of this XmlElement + * Find the first XmlElement child of this XmlElement * @param name Optional name of the child * @param ns Optional child namespace * @param noPrefix True to compare the tag without namespace prefix, false to @@ -1325,7 +1326,7 @@ public: { return XmlFragment::findElement(getChildren().skipNull(),name,ns,noPrefix); } /** - * Finds next child of this XmlElement + * Finds next XmlElement child of this XmlElement * @param prev Previous child * @param name Optional name of the child * @param ns Optional child namespace @@ -1357,6 +1358,12 @@ public: return c ? &(c->getText()) : 0; } + /** + * Get first XmlChild of this XmlElement + * @return The first XmlChild found. + */ + XmlChild* getFirstChild(); + /** * @return The first XmlText found in this XmlElement children */ @@ -1707,6 +1714,11 @@ public: virtual XmlText* xmlText() { return this; } + /** + * Helper method to check if the text held by this XmlText contains only spaces + * @return False if the text contains non space characters. + */ + bool onlySpaces(); private: String m_text; // The text };