diff options
author | Benjamin Paassen <bpaassen@techfak.uni-bielefeld.de> | 2015-02-22 11:48:19 +0100 |
---|---|---|
committer | Benjamin Paassen <bpaassen@techfak.uni-bielefeld.de> | 2015-02-22 11:48:19 +0100 |
commit | 255362d5f815ca0e04e18518bb3629d241af5117 (patch) | |
tree | 5e76d006f863c420eb5cd46a96ce2676717ee254 /src/core/XML.cpp | |
parent | e94dd497e760dcc72d048989f7d5d1c7e5aab862 (diff) |
corrected XML serialization for primitive text content regarding whitespace and newline handling and extended XMLTest to check that.
Diffstat (limited to 'src/core/XML.cpp')
-rw-r--r-- | src/core/XML.cpp | 114 |
1 files changed, 87 insertions, 27 deletions
diff --git a/src/core/XML.cpp b/src/core/XML.cpp index e25d18a..404af92 100644 --- a/src/core/XML.cpp +++ b/src/core/XML.cpp @@ -66,13 +66,82 @@ static std::string escapePredefinedEntities(const std::string &input) void Element::doSerialize(std::ostream &out, unsigned int tabdepth, bool pretty) { + bool hasText = false; if (pretty) { + // print tabs at the beginning, if we are in pretty mode. for (unsigned int t = 0; t < tabdepth; t++) { out << '\t'; } + /* + * if we are in pretty mode we also need to check if we have a text + * node as child. + * If so this changes our further output processing because of the way + * XML treats primitive data: The structure + * + * \code{.xml} + * <Element name="A"> + * <Text>content</Text> + * <Text>content2</Text> + * </Element> + * \endcode + * + * has to be serialized as + * + * \code{.xml} + * <A>contentcontent2</A> + * \endcode + * + * because otherwise we introduce whitespaces and newlines where no + * such things had been before. + * + * On the other hand the structure + * + * \code{.xml} + * <Element name="A"> + * <Element name="B"> + * <Text>content</Text> + * </Element> + * </Element> + * \endcode + * + * Can be serialized as + * + * \code{.xml} + * <A> + * <B>content</B> + * </A> + * \endcode + * + * As last example consider the case + * + * \code{.xml} + * <Element name="A"> + * <Element name="B"> + * <Text>content</Text> + * </Element> + * <Text>content2</Text> + * </Element> + * \endcode + * + * Here the A-Element again has primitive text content, such that we + * are not allowed to prettify. It has to be serialized like this: + * + * \code{.xml} + * <A><B>content</B>content2</A> + * \endcode + * + * + */ + for (auto n : children) { + if (n->isa(&RttiTypes::XMLText)) { + hasText = true; + break; + } + } } + out << '<'; - if(!nspace.empty()){ + if (!nspace.empty()) { out << nspace << ":"; } out << name; @@ -88,19 +157,19 @@ void Element::doSerialize(std::ostream &out, unsigned int tabdepth, bool pretty) } } else { out << ">"; - if (pretty) { + if (pretty && !hasText) { out << std::endl; } - for (auto &n : children) { - n->doSerialize(out, tabdepth + 1, pretty); + for (auto n : children) { + n->doSerialize(out, tabdepth + 1, pretty && !hasText); } - if (pretty) { + if (pretty && !hasText) { for (unsigned int t = 0; t < tabdepth; t++) { out << '\t'; } } out << "</"; - if(!nspace.empty()){ + if (!nspace.empty()) { out << nspace << ":"; } out << name << ">"; @@ -112,29 +181,20 @@ void Element::doSerialize(std::ostream &out, unsigned int tabdepth, bool pretty) void Text::doSerialize(std::ostream &out, unsigned int tabdepth, bool pretty) { - if (pretty) { - for (unsigned int t = 0; t < tabdepth; t++) { - out << '\t'; - } - } out << escapePredefinedEntities(text); - if (pretty) { - out << std::endl; - } } } -namespace RttiTypes -{ - const Rtti XMLNode = RttiBuilder<xml::Node>("XMLNode"); - const Rtti XMLElement = - RttiBuilder<xml::Element>("XMLElement") - .parent(&XMLNode) - .composedOf(&XMLNode) - .property("name", {&RttiTypes::String, - {[](const xml::Element *obj) { - return Variant::fromString(obj->getName()); - }}}); - const Rtti XMLText = RttiBuilder<xml::Text>("XMLText").parent(&XMLNode); -} +namespace RttiTypes { +const Rtti XMLNode = RttiBuilder<xml::Node>("XMLNode"); +const Rtti XMLElement = + RttiBuilder<xml::Element>("XMLElement") + .parent(&XMLNode) + .composedOf(&XMLNode) + .property("name", {&RttiTypes::String, + {[](const xml::Element *obj) { + return Variant::fromString(obj->getName()); + }}}); +const Rtti XMLText = RttiBuilder<xml::Text>("XMLText").parent(&XMLNode); } +}
\ No newline at end of file |