diff options
Diffstat (limited to 'src/plugins/xml')
| -rw-r--r-- | src/plugins/xml/XmlOutput.cpp | 116 | ||||
| -rw-r--r-- | src/plugins/xml/XmlOutput.hpp | 67 | 
2 files changed, 183 insertions, 0 deletions
diff --git a/src/plugins/xml/XmlOutput.cpp b/src/plugins/xml/XmlOutput.cpp new file mode 100644 index 0000000..00aae04 --- /dev/null +++ b/src/plugins/xml/XmlOutput.cpp @@ -0,0 +1,116 @@ +/* +    Ousía +    Copyright (C) 2014  Benjamin Paaßen, Andreas Stöckel + +    This program is free software: you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation, either version 3 of the License, or +    (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +    GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program.  If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "XmlOutput.hpp" + +#include <core/common/Variant.hpp> +#include <core/common/VariantWriter.hpp> + +namespace ousia { +namespace xml { + +void XmlTransformer::writeXml(Handle<Document> doc, std::ostream &out, +                              Logger &logger, bool pretty) +{ +	Manager &mgr = doc->getManager(); +	// the outermost tag is the document itself. +	Rooted<Element> document{new Element{mgr, {nullptr}, "document"}}; +	// then write imports for all references domains. +	for (auto d : doc->getDomains()) { +		Rooted<Element> import{ +		    new Element{mgr, +		                document, +		                "import", +		                {{"rel", "domain"}, {"src", d->getName() + ".oxm"}}}}; +		document->addChild(import); +	} +	// transform the root element (and, using recursion, everything below it) +	Rooted<Element> root = +	    transformStructuredEntity(document, doc->getRoot(), logger, pretty); +	document->addChild(root); +	// then serialize. +	document->serialize(out, "<?xml version=\"1.0\"?>", pretty); +} + +Rooted<Element> XmlTransformer::transformStructuredEntity( +    Handle<Element> parent, Handle<StructuredEntity> s, Logger &logger, +    bool pretty) +{ +	Manager &mgr = parent->getManager(); +	// TODO: Is this the right handling? +	// copy the attributes. +	Variant attrs = s->getAttributes(); +	// build them. +	s->getDescriptor()->getAttributesDescriptor()->build(attrs, logger); +	// get the array representation. +	Variant::arrayType attrArr = attrs.asArray(); +	// transform them to string key-value pairs. +	NodeVector<Attribute> as = +	    s->getDescriptor()->getAttributesDescriptor()->getAttributes(); +	std::map<std::string, std::string> xmlAttrs; +	for (size_t a = 0; a < as.size(); a++) { +		xmlAttrs.emplace(as[a]->getName(), +		                 VariantWriter::writeJsonToString(attrArr[a], pretty)); +	} +	// create the XML element itself. +	Rooted<Element> elem{ +	    new Element{mgr, parent, s->getDescriptor()->getName(), xmlAttrs}}; +	// then transform the fields. +	NodeVector<FieldDescriptor> fieldDescs = +	    s->getDescriptor()->getFieldDescriptors(); +	for (size_t f = 0; f < fieldDescs.size(); f++) { +		NodeVector<StructureNode> field = s->getField(f); +		Rooted<FieldDescriptor> fieldDesc = fieldDescs[f]; +		// if this is not the default node create an intermediate node for it. +		Rooted<Element> par = elem; +		if (fieldDesc->getFieldType() != FieldDescriptor::FieldType::TREE && +		    !fieldDesc->isPrimitive()) { +			par = Rooted<Element>{new Element(mgr, elem, fieldDesc->getName())}; +			elem->addChild(par); +		} +		for (auto c : field) { +			// transform each child. +			Rooted<Node> child; +			if (c->isa(&RttiTypes::StructuredEntity)) { +				child = transformStructuredEntity( +				    par, c.cast<StructuredEntity>(), logger, pretty); +			} else if (c->isa(&RttiTypes::DocumentPrimitive)) { +				child = transformPrimitive(par, c.cast<DocumentPrimitive>(), +				                           logger, pretty); +			} +			// TODO: Handle Anchors +			if (child != nullptr) { +				par->addChild(child); +			} +		} +	} +	return elem; +} +Rooted<Text> XmlTransformer::transformPrimitive(Handle<Element> parent, +                                                Handle<DocumentPrimitive> p, +                                                Logger &logger, bool pretty) +{ +	Manager &mgr = parent->getManager(); +	// transform the primitive content. +	std::string textcontent = +	    VariantWriter::writeJsonToString(p->getContent(), pretty); +	Rooted<Text> text{new Text(mgr, parent, textcontent)}; +	return text; +} +} +}
\ No newline at end of file diff --git a/src/plugins/xml/XmlOutput.hpp b/src/plugins/xml/XmlOutput.hpp new file mode 100644 index 0000000..51d03f9 --- /dev/null +++ b/src/plugins/xml/XmlOutput.hpp @@ -0,0 +1,67 @@ +/* +    Ousía +    Copyright (C) 2014  Benjamin Paaßen, Andreas Stöckel + +    This program is free software: you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation, either version 3 of the License, or +    (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +    GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program.  If not, see <http://www.gnu.org/licenses/>. +*/ + +/** + * @file XmlOutput.hpp + * + * This provices an Output generator to serialize any given document to XML. + * + * @author Benjamin Paaßen (bpaassen@techfak.uni-bielefeld.de) + */ +#ifndef _OUSIA_XML_OUTPUT_HPP_ +#define _OUSIA_XML_OUTPUT_HPP_ + +#include <ostream> + +#include <core/model/Document.hpp> +#include <core/XML.hpp> + +namespace ousia { +namespace xml { + +class XmlTransformer { +private: +	Rooted<Element> transformStructuredEntity(Handle<Element> parent, +	                                          Handle<StructuredEntity> s, +	                                          Logger &logger, bool pretty); + +	Rooted<Text> transformPrimitive(Handle<Element> parent, +	                                   Handle<DocumentPrimitive> p, +	                                   Logger &logger, bool pretty); + +public: +	/** +	 * This writes an XML serialization of the given document to the given +	 * output stream. The serialization is  equivalent to the input XML format, +	 * safe for the domain references. TODO: Can we change this? If so: how? +	 * Note, though, that the serialization will not exploit transparency. +	 * TODO: Can we change that? +	 * +	 * @param doc    is some Document. +	 * @param out    is the output stream the XML serialization of the document +	 *               shall be written to. +	 * @param logger is the logger errors shall be written to. +	 * @param pretty is a flag that manipulates whether newlines and tabs are +	 *               used. +	 */ +	void writeXml(Handle<Document> doc, std::ostream &out, Logger &logger, +	              bool pretty); +}; +} +} +#endif
\ No newline at end of file  | 
