diff options
author | Benjamin Paassen <bpaassen@techfak.uni-bielefeld.de> | 2015-01-08 18:11:21 +0100 |
---|---|---|
committer | Benjamin Paassen <bpaassen@techfak.uni-bielefeld.de> | 2015-01-08 18:11:21 +0100 |
commit | 2c3b327739b79d5ba7fe931e205bec1ad320b360 (patch) | |
tree | 6afca317bcd036a51e37e4cbec3cddb6bdeaf555 | |
parent | 7269e0e232c7971248ffa47aa2ae44786f3d303a (diff) |
further extended the advanced document example, slightly improved XML serialization and fixed a bug in DemoOutput leading to errors if a section/paragraph had no heading.
-rw-r--r-- | src/core/XML.cpp | 29 | ||||
-rw-r--r-- | src/core/XML.hpp | 7 | ||||
-rw-r--r-- | src/core/model/Domain.hpp | 13 | ||||
-rw-r--r-- | src/plugins/html/DemoOutput.cpp | 50 | ||||
-rw-r--r-- | src/plugins/html/DemoOutput.hpp | 8 | ||||
-rw-r--r-- | test/core/model/TestAdvanced.hpp | 90 |
6 files changed, 136 insertions, 61 deletions
diff --git a/src/core/XML.cpp b/src/core/XML.cpp index 038cb86..7f03b35 100644 --- a/src/core/XML.cpp +++ b/src/core/XML.cpp @@ -4,12 +4,16 @@ namespace ousia { namespace xml { -void Node::serialize(std::ostream& out){ +void Node::serialize(std::ostream &out, const std::string &doctype) +{ out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; + if (doctype != "") { + out << doctype << "\n"; + } doSerialize(out, 0); } -void Element::doSerialize(std::ostream& out, unsigned int tabdepth) +void Element::doSerialize(std::ostream &out, unsigned int tabdepth) { for (unsigned int t = 0; t < tabdepth; t++) { out << '\t'; @@ -18,17 +22,22 @@ void Element::doSerialize(std::ostream& out, unsigned int tabdepth) for (auto &a : attributes) { out << ' ' << a.first << "=\"" << a.second << '\"'; } - out << ">\n"; - for (auto &n : children) { - n->doSerialize(out, tabdepth + 1); - } - for (unsigned int t = 0; t < tabdepth; t++) { - out << '\t'; + // if we have no children, we close the tag immediately. + if (children.size() == 0) { + out << "/>\n"; + } else { + out << ">\n"; + for (auto &n : children) { + n->doSerialize(out, tabdepth + 1); + } + for (unsigned int t = 0; t < tabdepth; t++) { + out << '\t'; + } + out << "</" << name << ">\n"; } - out << "</" << name << ">\n"; } -void Text::doSerialize(std::ostream& out, unsigned int tabdepth) +void Text::doSerialize(std::ostream &out, unsigned int tabdepth) { for (unsigned int t = 0; t < tabdepth; t++) { out << '\t'; diff --git a/src/core/XML.hpp b/src/core/XML.hpp index 9ca124a..51ef6fd 100644 --- a/src/core/XML.hpp +++ b/src/core/XML.hpp @@ -64,9 +64,12 @@ public: /** * This method writes an XML prolog and the XML representing the current * node, including all children, to the given output stream. - * @param out is the output stream the serialized data shall be written to. + * @param out is the output stream the serialized data shall be + * written to. + * @param doctype enables you to add a prefix after the XML prolog + * specifying the doctype. */ - void serialize(std::ostream &out); + void serialize(std::ostream &out, const std::string & doctype = ""); /** * This method just writes the XML representation of this node to the * output stream, without the XML prolog. diff --git a/src/core/model/Domain.hpp b/src/core/model/Domain.hpp index 96e13c7..8d5de0c 100644 --- a/src/core/model/Domain.hpp +++ b/src/core/model/Domain.hpp @@ -261,11 +261,6 @@ protected: VisitorSet &visited) override; public: - /** - * Note, that this flag will always be set to "false" for non-primitive - * FieldDescriptors, because in that case the cardinalities regulate - * whether children have to be inserted or not. - */ const bool optional; // TODO: What about the name of default fields? @@ -305,15 +300,19 @@ public: * TREE for the main or default structure or SUBTREE * for supporting structures. * @param name is the name of this field. + * @param optional should be set to 'false' is this field needs to be + * filled in order for an instance of the parent + * Descriptor to be valid. */ FieldDescriptor(Manager &mgr, Handle<Descriptor> parent, FieldType fieldType = FieldType::TREE, - std::string name = "") + std::string name = "", + bool optional = false) : Node(mgr, std::move(name), parent), children(this), fieldType(fieldType), // TODO: What would be a wise initialization of the primitiveType? - optional(false) + optional(optional) { } diff --git a/src/plugins/html/DemoOutput.cpp b/src/plugins/html/DemoOutput.cpp index 035ba25..eac240b 100644 --- a/src/plugins/html/DemoOutput.cpp +++ b/src/plugins/html/DemoOutput.cpp @@ -30,10 +30,18 @@ void DemoHTMLTransformer::writeHTML(Handle<model::Document> doc, { Manager &mgr = doc->getManager(); // Create an XML object tree for the document first. - Rooted<xml::Element> html{new xml::Element{mgr, "html"}}; + Rooted<xml::Element> html{new xml::Element{ + mgr, "html", {{"xlmns", "http://www.w3.org/1999/xhtml"}}}}; // add the head Element Rooted<xml::Element> head{new xml::Element{mgr, "head"}}; html->children.push_back(head); + // add the meta element. + Rooted<xml::Element> meta{ + new xml::Element{mgr, + "meta", + {{"http-equiv", "Content-Type"}, + {"content", "text/html; charset=utf-8"}}}}; + head->children.push_back(meta); // add the title Element with Text Rooted<xml::Element> title{new xml::Element{mgr, "title"}}; head->children.push_back(title); @@ -56,20 +64,21 @@ void DemoHTMLTransformer::writeHTML(Handle<model::Document> doc, body->children.push_back(book); // After the content has been transformed, we serialize it. - html->serialize(out); + html->serialize( + out, + "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n" + "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"); } /** * This is just for easier internal handling. */ -enum class SectionType { BOOK, CHAPTER, SECTION, SUBSECTION, NONE }; +enum class SectionType { BOOK, SECTION, SUBSECTION, NONE }; SectionType getSectionType(const std::string &name) { if (name == "book") { return SectionType::BOOK; - } else if (name == "chapter") { - return SectionType::CHAPTER; } else if (name == "section") { return SectionType::SECTION; } else if (name == "subsection") { @@ -79,7 +88,8 @@ SectionType getSectionType(const std::string &name) } } -Rooted<xml::Element> DemoHTMLTransformer::transformSection(Handle<model::StructuredEntity> section) +Rooted<xml::Element> DemoHTMLTransformer::transformSection( + Handle<model::StructuredEntity> section) { Manager &mgr = section->getManager(); // check the section type. @@ -93,7 +103,8 @@ Rooted<xml::Element> DemoHTMLTransformer::transformSection(Handle<model::Structu Rooted<xml::Element> sec{ new xml::Element{mgr, "div", {{"class", secclass}}}}; // check if we have a heading. - if (section->hasField("heading")) { + if (section->hasField("heading") && + section->getField("heading").size() > 0) { Rooted<model::StructuredEntity> heading = section->getField("heading")[0]; std::string headingclass; @@ -101,14 +112,11 @@ Rooted<xml::Element> DemoHTMLTransformer::transformSection(Handle<model::Structu case SectionType::BOOK: headingclass = "h1"; break; - case SectionType::CHAPTER: - headingclass = "h2"; - break; case SectionType::SECTION: - headingclass = "h3"; + headingclass = "h2"; break; case SectionType::SUBSECTION: - headingclass = "h4"; + headingclass = "h3"; break; case SectionType::NONE: // this can not happen; @@ -152,14 +160,15 @@ Rooted<xml::Element> DemoHTMLTransformer::transformSection(Handle<model::Structu return sec; } -Rooted<xml::Element> DemoHTMLTransformer::transformParagraph(Handle<model::StructuredEntity> par) +Rooted<xml::Element> DemoHTMLTransformer::transformParagraph( + Handle<model::StructuredEntity> par) { Manager &mgr = par->getManager(); - // create the p xml::Element + // create the p Element Rooted<xml::Element> p{new xml::Element{mgr, "p"}}; // check if we have a heading. - if (par->hasField("heading")) { + if (par->hasField("heading") && par->getField("heading").size() > 0) { Rooted<model::StructuredEntity> heading = par->getField("heading")[0]; // put the heading in a strong xml::Element. Rooted<xml::Element> strong{new xml::Element{mgr, "strong"}}; @@ -172,7 +181,7 @@ Rooted<xml::Element> DemoHTMLTransformer::transformParagraph(Handle<model::Struc strong->children.push_back(n); } } - + // transform paragraph children to XML as well for (auto &n : par->getField()) { std::string childDescriptorName = n->getDescriptor()->getName(); @@ -189,5 +198,14 @@ Rooted<xml::Element> DemoHTMLTransformer::transformParagraph(Handle<model::Struc } return p; } + +// Rooted<xml::Element> +// DemoHTMLTransformer::transformList(Handle<model::StructuredEntity> list){ +// Manager &mgr = list->getManager(); +// // create the list Element, which is either ul or ol (depends on descriptor) +// std::string listclass = list->getDescriptor()->getName(); +// Rooted<xml::Element> l{new xml::Element{mgr, listclass}}; +// // iterate through +//} } } diff --git a/src/plugins/html/DemoOutput.hpp b/src/plugins/html/DemoOutput.hpp index 70a5daa..0819d7f 100644 --- a/src/plugins/html/DemoOutput.hpp +++ b/src/plugins/html/DemoOutput.hpp @@ -46,13 +46,7 @@ private: */ Rooted<xml::Element> transformSection(Handle<model::StructuredEntity> sec); Rooted<xml::Element> transformParagraph(Handle<model::StructuredEntity> par); - /** - * This method is to be called recursively to write a list to HTML. - * TODO: Implement - */ -// void writeList(Handle<StructuredEntity> sec, std::ostream& out, -// int tabdepth); - +// Rooted<xml::Element> transformList(Handle<model::StructuredEntity> list); //TODO: Implement emphasis. public: diff --git a/test/core/model/TestAdvanced.hpp b/test/core/model/TestAdvanced.hpp index 95c5402..bb7671a 100644 --- a/test/core/model/TestAdvanced.hpp +++ b/test/core/model/TestAdvanced.hpp @@ -26,7 +26,6 @@ namespace ousia { namespace model { - static Rooted<StructuredClass> resolveDescriptor(Handle<Domain> domain, const std::string &className) { @@ -76,14 +75,52 @@ static Rooted<Domain> constructHeadingDomain(Manager &mgr, return domain; } +static bool addText(Handle<StructuredEntity> parent, + std::vector<Handle<Domain>> &doms, + const std::string &content) +{ + // Add its text. + Rooted<StructuredEntity> text = + StructuredEntity::buildEntity(parent, doms, "text"); + if (text.isNull()) { + return false; + } + // And its primitive content + Variant content_var{content.c_str()}; + Rooted<DocumentPrimitive> primitive = + DocumentPrimitive::buildEntity(text, content_var, "content"); + if (primitive.isNull()) { + return false; + } + + return true; +} + +static bool addHeading(Handle<StructuredEntity> parent, + std::vector<Handle<Domain>> &doms, + const std::string &text) +{ + // Add the heading. + Rooted<StructuredEntity> heading = StructuredEntity::buildEntity( + parent, doms, "heading", "heading", {}, ""); + if (heading.isNull()) { + return false; + } + // Add its text. + if (!addText(heading, doms, text)) { + return false; + } + return true; +} + /** * This constructs a more advanced book document using not only the book * domain but also headings, emphasis and lists. * TODO: insert emphasis and lists. */ static Rooted<Document> constructAdvancedDocument(Manager &mgr, - Rooted<Domain> bookDom, - Rooted<Domain> headingDom) + Rooted<Domain> bookDom, + Rooted<Domain> headingDom) { std::vector<Handle<Domain>> doms{bookDom, headingDom}; @@ -96,29 +133,44 @@ static Rooted<Document> constructAdvancedDocument(Manager &mgr, if (book.isNull()) { return {nullptr}; } - { + // Add the heading. - Rooted<StructuredEntity> heading = StructuredEntity::buildEntity( - book, doms, "heading", "heading", {}, ""); - if (heading.isNull()) { + // TODO: use em here. + if (!addHeading(book, doms, + "Beantwortung der Frage: <em>Was ist Aufklärung?</em>")) { + return {nullptr}; + } + + // Add the main section. + Rooted<StructuredEntity> sec = + StructuredEntity::buildEntity(book, doms, "section"); + + // Add the heading. + if (!addHeading(sec, doms, "Was ist Aufklärung?")) { return {nullptr}; } + + // Add paragraph with main text. { + Rooted<StructuredEntity> p = + StructuredEntity::buildEntity(sec, doms, "paragraph"); // Add its text. - Rooted<StructuredEntity> text = - StructuredEntity::buildEntity(heading, doms, "text"); - if (text.isNull()) { + // TODO: Use em and strong here + if (!addText(p, doms, + " <strong>Aufklärung ist der Ausgang des Menschen aus " + "seiner selbstverschuldeten Unmündigkeit</strong>. " + "<em>Unmündigkeit</em> ist das Unvermögen, sich seines " + "Verstandes ohne Leitung eines anderen zu bedienen. " + "<em>Selbstverschuldet</em> ist diese Unmündigkeit, wenn " + "die Ursache derselben nicht am Mangel des Verstandes, " + "sondern der Entschließung und des Mutes liegt, sich " + "seiner ohne Leitung eines andern zu bedienen. <em>Sapere " + "aude! Habe Mut, dich deines eigenen Verstandes zu " + "bedienen!</em> ist also der Wahlspruch der " + "Aufklärung.")) { return {nullptr}; } - // And its primitive content - // TODO: use em here. - Variant content {"Beantwortung der Frage: <em>Was ist Aufklärung?</em>"}; - Rooted<DocumentPrimitive> main_primitive = - DocumentPrimitive::buildEntity(text, content, "content"); - if (main_primitive.isNull()) { - return {nullptr}; - } - }} + } return doc; } |