45#include <drain/Sprinter.h>
46#include <drain/FlexibleVariable.h>
51#include "ReferenceMap.h"
58class XML :
protected ReferenceMap2<FlexibleVariable> {
66 static const intval_t UNDEFINED = 0;
67 static const intval_t COMMENT = 1;
68 static const intval_t CTEXT = 2;
69 static const intval_t SCRIPT = 3;
70 static const intval_t STYLE = 4;
71 static const intval_t STYLE_SELECT = 5;
83 template <
class T2,
class ...T3>
85 bool typeIs(
const T2 & arg,
const T3... args)
const {
86 if (type ==
static_cast<intval_t
>(arg)){
103 intval_t type = XML::UNDEFINED;
116 static int getCount(){
122 bool isUndefined()
const {
123 return type == UNDEFINED;
127 bool isComment()
const {
128 return type == COMMENT;
132 bool isCText()
const {
133 return type == CTEXT;
137 bool isStyle()
const {
138 return type == STYLE;
142 bool isScript()
const {
143 return type == SCRIPT;
189 template <
char C=
'\0',
typename ...TT>
207 template <
class ...T>
223 void setText(
const std::string & s);
225 template <
class ...T>
226 void setText(
const T & ...args) {
231 const std::string & getText()
const {
236 const std::string & getUrl(){
241 void setUrl(
const std::string & s){
246 template <
class ...T>
248 void setName(
const T & ...args){
257 return map_t::empty();
261 const map_t & getAttributes()
const {
267 map_t & getAttributes(){
287 V get(
const std::string & key,
const V & defaultValue)
const {
292 std::string get(
const std::string & key,
const char * defaultValue)
const {
300 (*this)[key] = value;
307 (*this)[key] = value;
314 (*this)[key] = value;
319 void removeAttribute(
const std::string & s){
321 if (it != this->end()){
336 const StyleXML & getStyle()
const {
341 void setStyle(
const StyleXML & s){
346 void setStyle(
const std::string & value){
348 if (type == UNDEFINED){
349 mout.reject<LOG_WARNING>(
"setting style for UNDEFINED elem: ", value);
350 mout.unimplemented<LOG_WARNING>(
"future option: set type to STYLE_SELECT");
352 else if (type == STYLE){
353 mout.reject<LOG_WARNING>(
"not setting style for STYLE elem: ", value);
361 void setStyle(
const char *value){
362 setStyle(std::string(value));
366 void setStyle(
const std::string & key,
const std::string & value){
368 if (type == UNDEFINED){
369 mout.reject<LOG_WARNING>(
"setting style for UNDEFINED elem: ", key,
'=', value);
370 mout.unimplemented<LOG_WARNING>(
"future option: set type to STYLE_SELECT");
372 else if (type == STYLE){
373 mout.reject<LOG_WARNING>(
"not setting style for STYLE elem: ", value);
376 this->style[key] = value;
390 void setStyle(
const std::string & key,
const std::initializer_list<V> &l){
396 this->style[key] = l;
406 void setStyle(
const std::string & key,
const V & value){
409 drain::Logger(__FILE__, __FUNCTION__).
reject<LOG_WARNING>(
"Setting style of STYLE: ", key,
"=", value);
412 this->style[key] = value;
417 void setStyle(
const std::initializer_list<std::pair<const char *,const drain::Variable> > &args){
441 ClassListXML classList;
445 const ClassListXML & getClasses()
const {
449 template <
typename ... TT>
452 classList.add(args...);
461 return classList.has(cls);
465 void removeClass(
const std::string & s) {
476 void specificAttributesToStream(std::ostream & ostr)
const;
479 enum tag_display_mode {
483 EMPTY_TAG = OPENING_TAG | CLOSING_TAG,
489 std::ostream & nodeToStream(std::ostream & ostr, tag_display_mode mode=EMPTY_TAG)
const = 0;
496 std::ostream &
toStream(std::ostream & ostr,
const TR & tree,
const std::string & defaultTag=
"ELEM",
int indent=0);
501 void xmlAttribToStream(std::ostream &ostr,
const std::string & key,
const V &value){
516 template <
typename TX>
523 dst->setType(src->getType());
524 dst->setText(src->ctext);
525 dst->getAttributes() = src->getAttributes();
535 template <
typename TX>
537 TX &
xmlAssign(TX & dst,
const typename TX::xml_node_t & src){
557 template <
typename X>
564 dst.setType(src.getType());
565 dst.getAttributes().importMap(src.getAttributes());
566 dst.setStyle(src.getStyle());
568 dst.ctext = src.ctext;
578 template <
typename TX,
typename V>
589 template <
typename TX>
592 TX &
xmlAssign(TX & tree, std::initializer_list<std::pair<const char *,const Variable> > l){
594 switch (
static_cast<intval_t
>(tree->getType())){
596 for (
const auto & entry: l){
597 TX & elem = tree[entry.first];
598 elem->setType(STYLE_SELECT);
603 tree->setType(STYLE_SELECT);
621 template <
typename TX>
624 if (tree->isUndefined()){
625 tree->setType(CTEXT);
655 template <
typename TX>
657 TX & xmlAppendString(TX & tree,
const std::string & s){
658 if (tree->isCText()){
662 else if (tree->isUndefined()){
663 tree->setType(CTEXT);
670 TX & child = tree.addChild();
671 child->setType(CTEXT);
682 template <
typename TX>
684 TX &
xmlSetType(TX & tree,
const typename TX::node_data_t::xml_tag_t & type){
695 template <
typename T>
698 typename T::node_data_t::xml_tag_t type = xmlRetrieveDefaultType(tree.data);
701 return tree[key](type);
708 k << tree.getChildren().size();
709 return tree[k.str()](type);
713 template <
typename N>
715 typename N::xml_tag_t xmlRetrieveDefaultType(
const N & parentNode){
716 typedef typename N::xml_default_elem_map_t map_t;
717 const typename map_t::const_iterator it = N::xml_default_elems.find(parentNode.getNativeType());
718 if (it != N::xml_default_elems.end()){
722 return static_cast<typename N::xml_tag_t
>(0);
746std::ostream &
XML::toStream(std::ostream & ostr,
const TR & tree,
const std::string & defaultTag,
int indent){
750 const typename TR::container_t & children = tree.getChildren();
753 const typename TR::node_data_t & data = tree.data;
755 tag_display_mode mode = EMPTY_TAG;
758 data.nodeToStream(ostr, mode);
763 if (!data.ctext.empty()){
765 if (data.isSingular()){
774 if (!children.empty()){
776 if (data.isSingular()){
777 mout.
warn(
"Singular (hence normally empty) element <", tree->getTag(),
" id='", data.getId(),
"' ...> has ", children.size(),
" children?");
782 if (data.isExplicit()){
785 else if (data.isSingular()){
792 std::string fill(2*indent,
' ');
794 data.nodeToStream(ostr, mode);
796 if (mode == EMPTY_TAG){
801 else if (data.isStyle()){
806 if (!data.ctext.empty()){
808 ostr << fill << data.ctext;
813 if (!data.getAttributes().empty()){
814 mout.
warn(
"STYLE elem ", data.getId(),
" contains attributes, probably meant as style: ", sprinter(data.getAttributes()));
815 ostr <<
"\n\t /" <<
"* <!-- DISCARDED attribs ";
817 ostr <<
" /--> *" <<
"/" <<
'\n';
820 if (!data.style.empty()){
824 for (
const auto & attr: data.style){
826 Sprinter::pairToStream(ostr, attr, StyleXML::styleRecordLayout);
840 for (
const auto & entry: tree.getChildren()){
842 if (entry.second->isComment()){
844 ostr << fill <<
"/* "<< entry.second->ctext <<
" */" <<
'\n';
849 if (!entry.second->ctext.empty()){
851 ostr << fill <<
" " << entry.first <<
" {" << entry.second->ctext <<
"} /* CTEXT */ \n";
854 if (!entry.second->getAttributes().empty()){
855 ostr << fill <<
" " << entry.first <<
" {\n";
856 for (
const auto & attr: entry.second->getAttributes()){
858 ostr << attr.first <<
':' << attr.second <<
';';
861 ostr << fill <<
" }\n";
877 if (data.isScript()){
886 bool ALL_CTEXT =
true;
888 for (
const auto & entry: children){
889 if (!entry.second->isCText()){
900 for (
const auto & entry: children){
916 for (
const auto & entry: children){
917 toStream(ostr, entry.second, entry.first, indent+1);
927 data.nodeToStream(ostr, CLOSING_TAG);
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:312
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition Log.h:430
Logger & reject(const TT &... args)
Some input has been rejected, for example by a syntax.
Definition Log.h:610
A map of references to base type scalars, arrays or std::string; changing values in either are equiva...
Definition ReferenceMap.h:69
ref_t & link(const std::string &key, F &x)
Associates a map entry with a variable.
Definition ReferenceMap.h:84
map_t::iterator iterator
Needed?
Definition SmartMap.h:80
std::string get(const std::string &key, const std::string &defaultValue) const
Retrieves a value, or default value if value is unset.
Definition SmartMap.h:127
static std::ostream & toStream(std::ostream &ostr, const std::initializer_list< T > &x, const SprinterLayout &layout=defaultLayout)
New (experimental)
Definition Sprinter.h:420
Definition StringBuilder.h:58
static void commentToStream(std::ostream &ostr, const T &v)
Practical utility, helps in adding C++ code commenting...
Definition StyleXML.h:69
VariableT is a final class applied through typedefs Variable, Reference and FlexibleVariable.
Definition VariableT.h:87
bool typeIs(const T2 &arg, const T3... args) const
Return true, if type is any of the arguments.
Definition XML.h:85
virtual bool isExplicit() const
Tell if this element should always have an explicit closing tag even when empty, like <STYLE></STYLE>
Definition XML.cpp:85
static TX & xmlAssign(TX &tree, const V &arg)
Assign another tree structure to another.
Definition XML.h:580
virtual bool isSingular() const
Tell if this element should always have an explicit closing tag even when empty, like <STYLE></STYLE>
Definition XML.cpp:79
void addClass(const TT &... args)
Style class.
Definition TreeXML.h:220
void setId()
Makes ID a visible attribute.
Definition XML.h:178
void setStyle(const std::string &key, const std::initializer_list< V > &l)
Set style of an element.
Definition XML.h:390
const std::string & getId() const
Returns ID of this element. Hopefully a unique ID...
Definition XML.h:197
virtual void setAttribute(const std::string &key, const char *value)
Default implementation. Needed for handling units in strings, like "50%" or "640px".
Definition XML.h:306
static TX & xmlAssignString(TX &tree, const std::string &s)
When assigning a string, create new element unless the element itself is of type CTEXT.
Definition XML.h:623
static const std::map< char, std::string > encodingMap
User may optionally filter attributes and CTEST with this using StringTools::replace(XML::encodingMap...
Definition XML.h:75
void setId(const TT &...args)
Concatenates arguments to an id.
Definition XML.h:191
virtual void setAttribute(const std::string &key, const std::string &value)
Default implementation. Needed for handling units in strings, like "50%" or "640px".
Definition TreeXML.h:166
static TX & xmlSetType(TX &tree, const typename TX::node_data_t::xml_tag_t &type)
Definition XML.h:684
static std::ostream & toStream(std::ostream &ostr, const TR &tree, const std::string &defaultTag="ELEM", int indent=0)
Definition XML.h:746
static T & xmlAddChild(T &tree, const std::string &key)
Definition XML.h:697
static TX & xmlAssign(TX &tree, std::initializer_list< std::pair< const char *, const Variable > > l)
Tree.
Definition XML.h:592
static TX & xmlAssign(TX &dst, const typename TX::xml_node_t &src)
Assign another tree structure to another.
Definition XML.h:537
virtual void clear()
Clear style, class and string data but keep the element type.
Definition XML.cpp:73
void reset()
Clear style, class and string data as well as the element type.
Definition XML.h:168
void setStyle(const std::string &key, const V &value)
For element/class/id, assign ...
Definition XML.h:406
virtual void setText(const std::string &s)
Assign the text content of this node. If the node type is undefined, set it to CTEXT.
Definition XML.cpp:97
void setComment(const T &...args)
Make this node a comment. Contained tree will not be deleted. In current version, attributes WILL be ...
Definition XML.h:209
void setAttribute(const std::string &key, const V &value)
"Final" implementation.
Definition XML.h:313
static X & xmlAssignNode(X &dst, const X &src)
Assign another tree structure to another.
Definition XML.h:559
static TX & xmlAssign(TX &dst, const TX &src)
Assign another tree structure to another.
Definition XML.h:518
bool hasClass(const V &cls) const
Definition XML.h:460
std::string id
Some general-purpose.
Definition TreeXML.h:95
void setId(const std::string &s)
Makes ID a visible attribute, with a given value.
Definition XML.h:184
Definition DataSelector.cpp:1277