From 4fec7e73201ed50e4a4157cb1ea1f1c63566dd89 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sun, 28 Feb 2016 16:49:17 +0200 Subject: Menu customization --- web/xhtml-fragment | 48 +++++++++++++++++++++ web/xhtml-fragment.cxx | 115 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+) create mode 100644 web/xhtml-fragment create mode 100644 web/xhtml-fragment.cxx (limited to 'web') diff --git a/web/xhtml-fragment b/web/xhtml-fragment new file mode 100644 index 0000000..a0964b0 --- /dev/null +++ b/web/xhtml-fragment @@ -0,0 +1,48 @@ +// file : web/xhtml-fragment -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef WEB_XHTML_FRAGMENT +#define WEB_XHTML_FRAGMENT + +#include +#include +#include // pair + +#include +#include + +namespace web +{ + namespace xhtml + { + // A parsed (via xml::parser) XHTML fragment that can later be serialized + // to xml::serializer. + // + class fragment + { + public: + fragment () = default; + + // Parse string as XHTML document fragment. The fragment should be + // complete, in the sense that all elements should have closing tags. + // Elements and attributes are considered to be in the namespace of the + // entire XHTML document, so no namespace should be specified for them. + // Do not validate against XHTML vocabulary. Can throw xml::parsing + // exception. + // + fragment (const std::string& xhtml, const std::string& input_name); + + void + operator() (xml::serializer&) const; + + bool + empty () const {return events_.empty ();} + + private: + std::vector> events_; + }; + } +} + +#endif // WEB_XHTML_FRAGMENT diff --git a/web/xhtml-fragment.cxx b/web/xhtml-fragment.cxx new file mode 100644 index 0000000..34247dd --- /dev/null +++ b/web/xhtml-fragment.cxx @@ -0,0 +1,115 @@ +// file : web/xhtml-fragment.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#include +#include + +#include +#include + +#include + +using namespace std; +using namespace xml; + +namespace web +{ + namespace xhtml + { + fragment:: + fragment (const string& text, const string& name) + { + // To parse the fragment make it a valid xml document, wrapping with the + // root element. + // + string doc ("" + text + ""); + + parser p ( + doc.c_str (), + doc.size (), + name, + parser::receive_elements | parser::receive_characters | + parser::receive_attributes_event); + + for (parser::event_type e: p) + { + switch (e) + { + case parser::start_element: + case parser::start_attribute: + { + const auto& n (p.qname ()); + + if (!n.namespace_ ().empty ()) + throw parsing ( + name, p.line (), p.column (), "namespace is not allowed"); + + events_.emplace_back (e, n.name ()); + break; + } + case parser::end_element: + case parser::end_attribute: + { + events_.emplace_back (e, ""); + break; + } + case parser::characters: + { + events_.emplace_back (e, p.value ()); + break; + } + default: + assert (false); + } + } + + // Unwrap the fragment removing the root element events. + // + assert (events_.size () >= 2); + events_.erase (events_.begin ()); + events_.pop_back (); + } + + void fragment:: + operator() (serializer& s) const + { + for (const auto& e: events_) + { + switch (e.first) + { + case parser::start_element: + { + s.start_element (xmlns, e.second); + break; + } + + case parser::start_attribute: + { + s.start_attribute (e.second); + break; + } + case parser::end_element: + { + s.end_element (); + break; + } + case parser::end_attribute: + { + s.end_attribute (); + break; + } + case parser::characters: + { + s.characters (e.second); + break; + } + default: + assert (false); + } + } + } + } +} -- cgit v1.1