summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Paassen <bpaassen@techfak.uni-bielefeld.de>2015-01-08 18:11:21 +0100
committerBenjamin Paassen <bpaassen@techfak.uni-bielefeld.de>2015-01-08 18:11:21 +0100
commit2c3b327739b79d5ba7fe931e205bec1ad320b360 (patch)
tree6afca317bcd036a51e37e4cbec3cddb6bdeaf555
parent7269e0e232c7971248ffa47aa2ae44786f3d303a (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.cpp29
-rw-r--r--src/core/XML.hpp7
-rw-r--r--src/core/model/Domain.hpp13
-rw-r--r--src/plugins/html/DemoOutput.cpp50
-rw-r--r--src/plugins/html/DemoOutput.hpp8
-rw-r--r--test/core/model/TestAdvanced.hpp90
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;
}