45#include <drain/FlexibleVariable.h>
46#include <drain/MapTools.h>
47#include <drain/Sprinter.h>
48#include <drain/StringTools.h>
53#include "ReferenceMap.h"
64class XML :
protected std::map<std::string,FlexibleVariable> {
67 typedef std::map<std::string,FlexibleVariable> map_t;
74 const map_t & getMap()
const {
83 static const intval_t UNDEFINED = 0;
84 static const intval_t COMMENT = 1;
85 static const intval_t CTEXT = 2;
86 static const intval_t SCRIPT = 3;
87 static const intval_t STYLE = 4;
88 static const intval_t STYLE_SELECT = 5;
89 static const intval_t JAVASCRIPT = 6;
90 static const intval_t JAVASCRIPT_SCOPE = 7;
98 NONBREAKABLE_SPACE =
' ',
141 void setType(
const T &t){
142 const intval_t t2 =
static_cast<intval_t
>(t);
159 const intval_t & getType()
const {
166 return type != UNDEFINED;
173 template <
class T2,
class ...T3>
175 bool typeIs(
const T2 & arg,
const T3... args)
const {
176 if (type ==
static_cast<intval_t
>(arg)){
191 static int getCount(){
197 bool isUndefined()
const {
198 return type == UNDEFINED;
202 bool isComment()
const {
203 return type == COMMENT;
207 bool isCText()
const {
208 return type == CTEXT;
212 bool isStyle()
const {
213 return type == STYLE;
217 bool isScript()
const {
218 return type == SCRIPT;
222 bool isScopeJS()
const {
223 return type == JAVASCRIPT_SCOPE;
259 getMap()[
"id"].
link(
id);
266 getMap()[
"id"].
link(
id=s);
271 template <
char C=
'\0',
typename ...TT>
290 template <
class ...T>
306 void setText(
const std::string & s);
308 template <
class ...T>
309 void setText(
const T & ...args) {
313 template <
class ...T>
314 void setTextSafe(
const T & ...args) {
322 const std::string & getText()
const {
327 const std::string & getUrl(){
332 void setUrl(
const std::string & s){
337 template <
class ...T>
339 void setName(
const T & ...args){
354 return map_t::empty();
358 bool hasAttribute(
const std::string & key){
359 return MapTools::hasKey(getMap(), key);
363 const map_t & getAttributes()
const {
369 map_t & getAttributes(){
391 V get(
const std::string & key,
const V & defaultValue)
const {
398 std::string get(
const std::string & key,
const char * defaultValue)
const {
407 (*this)[key] = value;
414 (*this)[key] = value;
421 (*this)[key] = value;
426 void removeAttribute(
const std::string & s){
428 if (it != this->end()){
442 intval_t type = XML::UNDEFINED;
464 const StyleXML & getStyle()
const {
469 void setStyle(
const StyleXML & s){
474 void setStyle(
const std::string & value){
476 if (type == UNDEFINED){
477 mout.reject<LOG_WARNING>(
"setting style for UNDEFINED elem: ", value);
478 mout.unimplemented<LOG_WARNING>(
"future option: set type to STYLE_SELECT");
480 else if (type == STYLE){
481 mout.reject<LOG_WARNING>(
"not setting style for STYLE elem: ", value);
489 void setStyle(
const char *value){
490 setStyle(std::string(value));
494 void setStyle(
const std::string & key,
const std::string & value){
496 if (type == UNDEFINED){
497 mout.reject<LOG_WARNING>(
"setting style for UNDEFINED elem: ", key,
'=', value);
498 mout.unimplemented<LOG_WARNING>(
"future option: set type to STYLE_SELECT");
500 else if (type == STYLE){
501 mout.reject<LOG_WARNING>(
"not setting style for STYLE elem: ", value);
504 this->style[key] = value;
518 void setStyle(
const std::string & key,
const std::initializer_list<V> &l){
524 this->style[key] = l;
534 void setStyle(
const std::string & key,
const V & value){
537 drain::Logger(__FILE__, __FUNCTION__).
reject<LOG_WARNING>(
"Setting style of STYLE: ", key,
"=", value);
540 this->style[key] = value;
545 void setStyle(
const std::initializer_list<std::pair<const char *,const drain::Variable> > &args){
546 drain::SmartMapTools::setValues(style, args);
550 void setStyle(
const std::map<std::string, V> & args){
560 ClassListXML classList;
564 const ClassListXML & getClasses()
const {
568 template <
typename ... TT>
571 classList.add(args...);
580 return classList.has(cls);
584 void removeClass(
const std::string & s) {
595 void specificAttributesToStream(std::ostream & ostr)
const;
598 enum tag_display_mode {
602 EMPTY_TAG = OPENING_TAG | CLOSING_TAG,
608 std::ostream & nodeToStream(std::ostream & ostr, tag_display_mode mode=EMPTY_TAG)
const = 0;
614 std::ostream &
toStream(std::ostream & ostr,
const TR & tree,
const std::string & defaultTag=
"ELEM",
int indent=0);
634 static const std::map<char,char> keyMap = {
643 static const std::map<char,std::string> valueMap = {
644 {entity_t::QUOTE,
"'"},
645 {entity_t::LESS_THAN,
"(("},
646 {entity_t::GREATER_THAN,
"))"},
662 template <
typename N>
669 if (dst.getType() != src.getType()){
672 dst.setType(src.getType());
676 dst.setStyle(src.getStyle());
678 dst.ctext = src.ctext;
707DRAIN_ENUM_DICT(XML::entity_t);
708DRAIN_ENUM_OSTREAM(XML::entity_t);
711std::ostream &
XML::toStream(std::ostream & ostr,
const TR & tree,
const std::string & defaultTag,
int indent){
715 const typename TR::container_t & children = tree.getChildren();
718 const typename TR::node_data_t & data = tree.data;
720 tag_display_mode mode = EMPTY_TAG;
723 data.nodeToStream(ostr, mode);
728 if (!data.ctext.empty()){
730 if (data.isSingular()){
739 if (!children.empty()){
741 if (data.isSingular()){
742 mout.
warn(
"Singular (hence normally empty) element <", tree->getTag(),
" id='", data.getId(),
"' ...> has ", children.size(),
" children?");
747 if (data.isExplicit()){
750 else if (data.isSingular()){
757 std::string fill(2*indent,
' ');
759 data.nodeToStream(ostr, mode);
761 if (mode == EMPTY_TAG){
766 else if (data.isStyle()){
771 if (!data.ctext.empty()){
773 ostr << fill << data.ctext;
778 if (!data.getAttributes().empty()){
779 mout.
warn(
"STYLE elem ", data.getId(),
" contains attributes, probably meant as style: ", sprinter(data.getAttributes()));
780 ostr <<
"\n\t /" <<
"* <!-- DISCARDED attribs ";
782 ostr <<
" /--> *" <<
"/" <<
'\n';
785 if (!data.style.empty()){
789 for (
const auto & attr: data.style){
791 Sprinter::pairToStream(ostr, attr, StyleXML::styleRecordLayout);
805 for (
const auto & entry: tree.getChildren()){
807 if (entry.second->isComment()){
809 ostr << fill <<
"/* "<< entry.second->ctext <<
" */" <<
'\n';
814 if (!entry.second->ctext.empty()){
816 ostr << fill <<
" " << entry.first <<
" {" << entry.second->ctext <<
"} /* CTEXT */ \n";
819 if (!entry.second->getAttributes().empty()){
820 ostr << fill <<
" " << entry.first <<
" {\n";
821 for (
const auto & attr: entry.second->getAttributes()){
823 if (attr.first ==
"id"){
828 ostr << attr.first <<
':' << attr.second <<
';';
832 ostr << fill <<
" }\n";
848 if (data.isScript()){
858 bool ALL_CTEXT =
true;
860 for (
const auto & entry: children){
861 if (!entry.second->isCText()){
872 for (
const auto & entry: children){
889 for (
const auto & entry: children){
890 toStream(ostr, entry.second, entry.first, indent+1);
900 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:313
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition Log.h:431
Logger & reject(const TT &... args)
Some input has been rejected, for example by a syntax.
Definition Log.h:611
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
static std::ostream & toStream(std::ostream &ostr, const std::initializer_list< T > &x, const SprinterLayout &layout=defaultLayout)
New (experimental)
Definition Sprinter.h:424
Definition StringBuilder.h:58
static void commentToStream(std::ostream &ostr, const TT... args)
Practical utility, helps in adding C++ code commenting...
Definition StyleXML.h:72
VariableT is a final class applied through typedefs Variable, Reference and FlexibleVariable.
Definition VariableT.h:87
Base class for XML "nodes", to be data elements T for drain::Tree<T>
Definition TreeXML.h:80
static const std::map< char, std::string > & getEntityMap()
Handy map for converting characters to XML entities. Example: '&' -> "&".
Definition XML.cpp:189
bool typeIs(const T2 &arg, const T3... args) const
Return true, if type is any of the arguments.
Definition XML.h:175
virtual bool isExplicit() const
Tell if this element should always have an explicit closing tag even when empty, like <STYLE></STYLE>
Definition XML.cpp:150
bool typeIsSet() const
Return true, if type is any of the arguments.
Definition XML.h:165
static const std::map< char, std::string > & getKeyConversionMap()
Characters that must be avoided in XML attribute keys: space, tab, =.
Definition XML.cpp:85
virtual bool isSingular() const
Tell if this element should always have an explicit closing tag even when empty, like <STYLE></STYLE>
Definition XML.cpp:144
void addClass(const TT &... args)
Style class.
Definition TreeXML.h:220
void setId()
Makes ID a visible attribute.
Definition XML.h:258
void setStyle(const std::string &key, const std::initializer_list< V > &l)
Set style of an element.
Definition XML.h:518
const std::string & getId() const
Returns ID of this element. Hopefully a unique ID...
Definition XML.h:280
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:413
static const std::map< char, std::string > & getAttributeConversionMap()
Characters that must be avoided in XML attribute values: ".
Definition XML.cpp:100
static const std::map< char, std::string > & getCTextConversionMap()
Characters to avoid in XML free text: <, >, {, },.
Definition XML.cpp:112
static void xmlAttribToStream(std::ostream &ostr, const std::string &key, const V &value)
Handy map for converting characters to XML entities. Example: '&' -> "&".
Definition XML.h:630
void setId(const TT &...args)
Concatenates arguments to an id.
Definition XML.h:273
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 std::ostream & toStream(std::ostream &ostr, const TR &tree, const std::string &defaultTag="ELEM", int indent=0)
Definition XML.h:711
static N & xmlAssignNode(N &dst, const N &src)
Assign tree node (data) to another.
Definition XML.h:664
void reset()
Keep the element type but clear style, class and string data.
Definition XML.cpp:137
void setStyle(const std::string &key, const V &value)
For element/class/id, assign ...
Definition XML.h:534
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:155
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:292
XML()
User may optionally filter attributes and CTEST with this using StringTools::replace(XML::encodingMap...
Definition XML.h:131
void setAttribute(const std::string &key, const V &value)
"Final" implementation.
Definition XML.h:420
bool hasClass(const V &cls) const
Definition XML.h:579
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:265
Definition DataSelector.cpp:1277
VariableT< VariableInitializer< ReferenceT< VariableBase > > > FlexibleVariable
Value container supporting dynamic type with own memory and optional linking (referencing) of externa...
Definition FlexibleVariable.h:67
Default implementation.
Definition Type.h:541