Loading...
Searching...
No Matches
XML.h
1/*
2
3MIT License
4
5Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25 */
26/*
27Part of Rack development has been done in the BALTRAD projects part-financed
28by the European Union (European Regional Development Fund and European
29Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30 */
31/*
32 * TreeXML.h
33 *
34 * Created on: Jun 24, 2012
35 * Author: mpeura
36 */
37
38
39
40#ifndef DRAIN_XML
41#define DRAIN_XML
42
43#include <ostream>
44
45#include <drain/Sprinter.h>
46#include <drain/FlexibleVariable.h>
47
48#include "ClassXML.h"
49// #include "UtilsXML.h"
50// #include "Flags.h"
51#include "ReferenceMap.h"
52#include "StyleXML.h"
53
54namespace drain {
55
56
58class XML : protected ReferenceMap2<FlexibleVariable> {
59public:
60
61 typedef int intval_t;
62
63 // TODO:
64 // static const intval_t flag_OPEN = 128;
65 // static const intval_t flag_TEXT = 256;
66 static const intval_t UNDEFINED = 0;
67 static const intval_t COMMENT = 1; // || flag_TEXT
68 static const intval_t CTEXT = 2; // || flag_TEXT
69 static const intval_t SCRIPT = 3; // || flag_EXPLICIT || flag_TEXT
70 static const intval_t STYLE = 4; // || flag_EXPLICIT
71 static const intval_t STYLE_SELECT = 5;
72
73 enum entity_t {
74 AMPERSAND = '&',
75 LESS_THAN = '<',
76 EQUAL_TO = '=',
77 GREATER_THAN = '>',
78 NONBREAKABLE_SPACE = ' ',
79 QUOTE = '"',
80 CURLY_LEFT = '{',
81 CURLY_RIGHT = '}',
82 // ---
83 TAB = '\t',
84 NEWLINE = '\n',
85 // ---
86 DEGREE = 176,
87 };
88
89 /* Variants of entity map */
90
92 static
93 const std::map<char,std::string> & getKeyConversionMap();
94
96 static
97 const std::map<char,std::string> & getAttributeConversionMap();
98
100 static
101 const std::map<char,std::string> & getCTextConversionMap();
102
103
105 // OLD static const std::map<char,std::string> encodingMap;
106
108
109
110
111public:
112
113 inline
114 XML(){};
115
116 inline
117 XML(const XML &){
118
119 };
120
121 template <class T> // "final"
122 void setType(const T &t){ // DANGER, without cast?
123 const intval_t t2 = static_cast<intval_t>(t);
124 if (type != t2){
125 reset();
126 type = t2; // also UNDEFINED ok here
127 handleType(); // NOTE: problems, if copy constructor etc. calls setType on a base class – trying to link future members
128 }
129 // handleType(static_cast<T>(t)); REMOVED 2025/09
130 // in derived classes, eg. drain::image::BaseGDAL
131 // warning: case value ‘...’ not in enumerated type
132 }
133
134 // Consider this later, for user-defined (not enumerated) tag types.
135 // virtual
136 // void setType(const std::string & type);
137
138
139 inline
140 const intval_t & getType() const {
141 return type;
142 };
143
145 inline
146 bool typeIsSet() const {
147 return type != UNDEFINED;
148 };
149
151
154 template <class T2, class ...T3>
155 inline
156 bool typeIs(const T2 & arg, const T3... args) const {
157 if (type == static_cast<intval_t>(arg)){
158 return true;
159 }
160 else {
161 return typeIs(args...);
162 }
163 };
164
165
166 std::string ctext;
167
168 // Could be templated, behind Static?
169 static int nextID;
170
171 inline
172 static int getCount(){
173 return nextID;
174 }
175
176
177 inline
178 bool isUndefined() const {
179 return type == UNDEFINED;
180 }
181
182 inline
183 bool isComment() const {
184 return type == COMMENT;
185 }
186
187 inline
188 bool isCText() const {
189 return type == CTEXT;
190 }
191
192 inline
193 bool isStyle() const {
194 return type == STYLE;
195 }
196
197 inline
198 bool isScript() const {
199 return type == SCRIPT;
200 }
201
203 virtual
204 bool isSingular() const;
205
207 virtual
208 bool isExplicit() const;
209
211
219 void reset();
230
233 inline
234 void setId(){
235 link("id", id);
236 }
237
239 inline
240 void setId(const std::string & s){
241 link("id", id = s);
242 }
243
245 template <char C='\0', typename ...TT>
246 inline
247 void setId(const TT & ...args) {
248 link("id", id = drain::StringBuilder<C>(args...));
249 }
250
252 inline
253 const std::string & getId() const {
254 return id;
255 }
256
257
259
263 template <class ...T>
264 inline
265 void setComment(const T & ...args) {
266 this->clear(); // what if also uncommenting needed?
267 // this->clearClasses();
268 type = COMMENT;
269 setText(args...);
270 }
271
273
278 virtual // redef shows variadic args, below?
279 void setText(const std::string & s);
280
281 template <class ...T>
282 void setText(const T & ...args) {
283 setText(StringBuilder<>(args...).str()); // str() to avoid infinite loop
284 }
285
286 template <class ...T>
287 void setTextSafe(const T & ...args) {
288 std::string dst;
289 StringTools::replace(StringBuilder<>(args...).str(), getCTextConversionMap(), dst); // str() to avoid infinite loop
290 setText(dst);
291 //setText(StringTools::replace(m, StringBuilder<>(args...).str(), ctext)); // str() to avoid infinite loop
292 }
293
294 virtual inline
295 const std::string & getText() const {
296 return ctext;
297 }
298
299 inline
300 const std::string & getUrl(){
301 return url;
302 }
303
304 inline
305 void setUrl(const std::string & s){
306 url = s;
307 // ctext = s;
308 }
309
310 template <class ...T>
311 inline
312 void setName(const T & ...args){
313 setAttribute("data-name", drain::StringBuilder<>(args...).str());
314 }
315
316 inline
317 const FlexibleVariable & getName() const {
318 return (*this)["data-name"];
319 }
320
321
322 // ---------------- Attributes ---------------
323
324 virtual inline // shadows - consider virtual
325 bool empty() const {
326 return map_t::empty();
327 }
328
329 inline
330 const map_t & getAttributes() const {
331 return *this;
332 };
333
334 // Maybe controversial. Helps importing sets of variables.
335 inline
336 map_t & getAttributes(){
337 return *this;
338 };
339
340 // Rename getAttribute?
341 inline
342 const drain::FlexibleVariable & get(const std::string & key) const {
343 return (*this)[key];
344 }
345
346 // Rename getAttribute?
347 inline
348 drain::FlexibleVariable & get(const std::string & key){
349 return (*this)[key];
350 }
351
352
353 // Rename getAttribute?
354 template <class V>
355 inline
356 V get(const std::string & key, const V & defaultValue) const {
357 return map_t::get(key, defaultValue);
358 }
359
360 inline
361 std::string get(const std::string & key, const char * defaultValue) const {
362 return map_t::get(key, defaultValue);
363 }
364
366 // But otherways confusing?
367 virtual inline
368 void setAttribute(const std::string & key, const std::string &value){
369 (*this)[key] = value;
370 }
371
373 // But otherways confusing?
374 virtual inline
375 void setAttribute(const std::string & key, const char *value){
376 (*this)[key] = value; // -> handleString()
377 }
378
380 template <class V>
381 inline
382 void setAttribute(const std::string & key, const V & value){
383 (*this)[key] = value; // -> handleString()
384 }
385
386
387 inline
388 void removeAttribute(const std::string & s){
389 iterator it = this->find(s);
390 if (it != this->end()){
391 this->erase(it);
392 }
393 }
394
395
396
397protected:
398
399 inline
400 bool typeIs() const {
401 return false;
402 };
403
404 intval_t type = XML::UNDEFINED;
405
406 // String, still easily allowing numbers through set("id", ...)
407 std::string id;
408 // Consider either/or
409 std::string url;
410
411 virtual inline
412 void handleType(){}; // = 0;
413
414
415public:
416
417 // ------------------ Style ---------------
418
419protected:
420
421 StyleXML style;
422
423public:
424
425 inline
426 const StyleXML & getStyle() const {
427 return style;
428 }
429
430 inline
431 void setStyle(const StyleXML & s){
432 style.clear();
433 SmartMapTools::setValues(style, s);
434 }
435
436 void setStyle(const std::string & value){
437 drain::Logger mout(__FILE__, __FUNCTION__);
438 if (type == UNDEFINED){
439 mout.reject<LOG_WARNING>("setting style for UNDEFINED elem: ", value);
440 mout.unimplemented<LOG_WARNING>("future option: set type to STYLE_SELECT");
441 }
442 else if (type == STYLE){
443 mout.reject<LOG_WARNING>("not setting style for STYLE elem: ", value); // , *this);
444 }
445 else {
446 SmartMapTools::setValues(style, value, ';', ':', "; \t\n"); // sep, equal, trim (also ';' ?)
447 }
448 }
449
450 inline
451 void setStyle(const char *value){
452 setStyle(std::string(value));
453 }
454
455 inline
456 void setStyle(const std::string & key, const std::string & value){
457 drain::Logger mout(__FILE__, __FUNCTION__);
458 if (type == UNDEFINED){
459 mout.reject<LOG_WARNING>("setting style for UNDEFINED elem: ", key, '=', value);
460 mout.unimplemented<LOG_WARNING>("future option: set type to STYLE_SELECT");
461 }
462 else if (type == STYLE){
463 mout.reject<LOG_WARNING>("not setting style for STYLE elem: ", value); // , *this);
464 }
465 else {
466 this->style[key] = value;
467 }
468 }
469
470
472
478 template <class V>
479 inline
480 void setStyle(const std::string & key, const std::initializer_list<V> &l){
481 // const std::initializer_list<Variable::init_pair_t > &l
482 if (type == STYLE){ // typeIs(STYLE) fails
483 drain::Logger mout(__FILE__, __FUNCTION__);
484 mout.warn("Setting style of STYLE? initializer_list<", drain::TypeName<V>::str(), "> = ", sprinter(l)); // , StyleXML::styleLineLayout ?
485 }
486 this->style[key] = l;
487 }
488
489
491
494 template <class V>
495 inline
496 void setStyle(const std::string & key, const V & value){
497
498 if (type == STYLE){
499 drain::Logger(__FILE__, __FUNCTION__).reject<LOG_WARNING>("Setting style of STYLE: ", key, "=", value);
500 }
501 else {
502 this->style[key] = value;
503 }
504 }
505
506 inline
507 void setStyle(const std::initializer_list<std::pair<const char *,const drain::Variable> > &args){
509 }
510
511
512
513protected:
514
515 // ------------------ Style Class ---------------
516
517 ClassListXML classList;
518
519public:
520
521 const ClassListXML & getClasses() const {
522 return classList;
523 }
524
525 template <typename ... TT>
526 inline
527 void addClass(const TT &... args) {
528 classList.add(args...);
529 }
530
534 template <class V>
535 inline
536 bool hasClass(const V & cls) const {
537 return classList.has(cls);
538 }
539
540 inline
541 void removeClass(const std::string & s) {
542 classList.remove(s);
543 }
544
545 inline
546 void clearClasses(){
547 classList.clear();
548 }
549
550
551 virtual
552 void specificAttributesToStream(std::ostream & ostr) const;
553
554
555 enum tag_display_mode {
556 FLEXIBLE_TAG = 0, // <TAG>...</TAG> or <TAG/>
557 OPENING_TAG= 1, // <TAG>
558 CLOSING_TAG = 2, // </TAG>
559 EMPTY_TAG = OPENING_TAG | CLOSING_TAG, // element has no descendants: <hr/>
560 NON_EMPTY_TAG, // opening and closing tags must appear, even when empty: <script></script>
561 };
562
563
564 virtual
565 std::ostream & nodeToStream(std::ostream & ostr, tag_display_mode mode=EMPTY_TAG) const = 0;
566
567
568
569 template <class TR>
570 static
571 std::ostream & toStream(std::ostream & ostr, const TR & tree, const std::string & defaultTag="ELEM", int indent=0);
572
574
576 static
577 const std::map<char,std::string> & getEntityMap();
578
580
584 template <class V>
585 static inline
586 void xmlAttribToStream(std::ostream &ostr, const std::string & key, const V &value){
587 //StringTools::replace(XML::encodingMap, data.ctext, ostr);
588 //ostr << ' ' << key << '=' << '"' << value << '"'; // << ' ';
589
590 static const std::map<char,char> keyMap = {
591 {' ','_'},
592 {'"','_'},
593 {'=','_'},
594 };
595 ostr << ' ';
596 StringTools::replace(key, keyMap, ostr); // XML::encodingMap
597 //StringTools::replace(getEntityMap(), key, ostr); // XML::encodingMap
598
599 static const std::map<char,std::string> valueMap = {
600 {entity_t::QUOTE, "'"},
601 {entity_t::LESS_THAN,"(("},
602 {entity_t::GREATER_THAN,"))"},
603 };
604 ostr << '=' << '"';
605 StringTools::replace(value, valueMap, ostr); // XML::encodingMap
606 //StringTools::replace(getEntityMap(), value, ostr); // XML::encodingMap
607 ostr << '"';
608 //<< key << '=' << '"' << value << '"'; // << ' ';
609 }
610
611 // ----------------- Static utilities for derived classes ----------------------
612
614
633
644
649 template <typename N>
650 static inline
651 N & xmlAssignNode(N & dst, const N & src){
652
653 if (&src != &dst){
654 //dst.clear(); // clear attributes,
655 //if (!dst.typeIs(src.getNativeType())){
656 if (dst.getType() != src.getType()){
657 dst.reset(); // clear attributes, style, cstring and type.
658 // Warning: does not create links.
659 dst.setType(src.getType());
660 }
661 dst.getAttributes().importMap(src.getAttributes());
662 dst.setStyle(src.getStyle());
663 // dst.setText(src.ctext); // wrong! set type to CTEXT
664 dst.ctext = src.ctext;
665 }
666
667 return dst;
668 }
669
670
672
683
711 // UNDER CONSTRUCTION!
713
753
808 /*
809 UNUSED!
810 template <typename T>
811 static
812 T & xmlGuessType(const typename T::node_data_t & parentNode, T & child){
813 typedef typename T::node_data_t::xml_default_elem_map_t map_t;
814 const typename map_t::const_iterator it = T::node_data_t::xml_default_elems.find(parentNode.getNativeType());
815 if (it != T::node_data_t::xml_default_elems.end()){
816 child->setType(it->second);
817 drain::Logger(__FILE__, __FUNCTION__).experimental<LOG_WARNING>("Default type set: ", child->getTag());
818 }
819 return child;
820 }
821 */
822
823
824
825};
826
827
828template <>
830
831DRAIN_ENUM_OSTREAM(XML::entity_t);
832
833template <class TR>
834std::ostream & XML::toStream(std::ostream & ostr, const TR & tree, const std::string & defaultTag, int indent){
835
836 drain::Logger mout(__FILE__,__FUNCTION__);
837
838 const typename TR::container_t & children = tree.getChildren();
839
840 // const XML & data = tree.data; // template type forcing, keep here for programming aid.
841 const typename TR::node_data_t & data = tree.data; // template used
842
843 tag_display_mode mode = EMPTY_TAG;
844
845 if (data.isCText()){ // this can be true only at root, and rarely so...? (because recursive call not reached, if ctext)
846 data.nodeToStream(ostr, mode);
847 // ostr << "<!--TX-->";
848 return ostr;
849 }
850
851 if (!data.ctext.empty()){
852 // mout.warn("Non-CTEXT-elem with ctext: <", data.getTag(), " id='", data.getId(), "' ...>, text='", data.ctext, "'");
853 if (data.isSingular()){
854 // mout.warn("Skipping CTEXT of a singular element <", tree->getTag(), " id='", data.getId(), "' ...> , CTEXT: '", data.ctext, "'");
855 mode = EMPTY_TAG;
856 }
857 else {
858 mode = OPENING_TAG;
859 }
860 }
861
862 if (!children.empty()){
863 mode = OPENING_TAG;
864 if (data.isSingular()){
865 mout.warn("Singular (hence normally empty) element <", tree->getTag(), " id='", data.getId(), "' ...> has ", children.size(), " children?");
866 }
867 }
868
869 // mout.attention("Hey! ", TypeName<TR>::str(), " with ", TypeName<typename TR::node_data_t>::str(), "Explicit ", data.isExplicit(), " or implicit ", data.isSingular());
870 if (data.isExplicit()){ // explicit
871 mode = OPENING_TAG;
872 }
873 else if (data.isSingular()){ // <br/> <hr/>
874 mode = EMPTY_TAG;
875 }
876 // Hence, is flexible, "bimodal", supports empty and open-close mode.
877
878 // Indent
879 // std::fill_n(std::ostream_iterator<char>(ostr), 2*indent, ' ');
880 std::string fill(2*indent, ' ');
881 ostr << fill;
882 data.nodeToStream(ostr, mode);
883
884 if (mode == EMPTY_TAG){
885 //ostr << "<!--ET-->";
886 ostr << '\n';
887 return ostr;
888 }
889 else if (data.isStyle()){
890 // https://www.w3.org/TR/xml/#sec-cdata-sect
891 // ostr << "<![CDATA[ \n";
892 // ostr << "<!-- STYLE -->"; WRONG!
893
894 if (!data.ctext.empty()){
895 // TODO: indent
896 ostr << fill << data.ctext;
897 StyleXML::commentToStream(ostr, " TEXT ");
898 ostr << '\n';
899 }
900
901 if (!data.getAttributes().empty()){
902 mout.warn("STYLE elem ", data.getId()," contains attributes, probably meant as style: ", sprinter(data.getAttributes()));
903 ostr << "\n\t /" << "* <!-- DISCARDED attribs ";
904 Sprinter::toStream(ostr, data.getAttributes()); //, StyleXML::styleRecordLayout
905 ostr << " /--> *" << "/" << '\n';
906 }
907
908 if (!data.style.empty()){
909 ostr << fill;
910 StyleXML::commentToStream(ostr, "STYLE OBJ");
911 ostr << '\n';
912 for (const auto & attr: data.style){
913 ostr << fill << " ";
914 Sprinter::pairToStream(ostr, attr, StyleXML::styleRecordLayout); // {" :;"}
915 //attr.first << ':' attr.first << ':';
916 ostr << '\n';
917 }
918 // ostr << fill << "}\n";
919 // Sprinter::sequenceToStream(ostr, entry.second->getAttributes(), StyleXML::styleRecordLayoutActual);
920 // ostr << '\n';
921 }
922 ostr << '\n';
923
924 ostr << fill;
925 StyleXML::commentToStream(ostr, "style ELEMS");
926 ostr << '\n';
927
928 for (const auto & entry: tree.getChildren()){
929
930 if (entry.second->isComment()){
931 // StringTools::replace();
932 ostr << fill << "/* "<< entry.second->ctext << " */" << '\n';
933 // XML::toStream(ostr, entry.second, defaultTag, indent); // indent not used?
934 continue;
935 }
936
937 if (!entry.second->ctext.empty()){
938 //ostr << fill << "<!-- elem("<< entry.first << ") ctext /-->" << '\n';
939 ostr << fill << " " << entry.first << " {" << entry.second->ctext << "} /* CTEXT */ \n";
940 }
941
942 if (!entry.second->getAttributes().empty()){
943 ostr << fill << " " << entry.first << " {\n";
944 for (const auto & attr: entry.second->getAttributes()){
945 ostr << fill << " ";
946 if (attr.first == "id"){
947 StyleXML::commentToStream(ostr, "id=", attr.second);
948 // mout.suspicious("Style elem has id (", attr.second, ")");
949 }
950 else {
951 ostr << attr.first << ':' << attr.second << ';';
952 }
953 ostr << '\n';
954 }
955 ostr << fill << " }\n";
956 ostr << '\n';
957 }
958
959 }
960 ostr << "\n"; // end CTEXT
961 // ostr << " ]]>\n"; // end CTEXT
962 // end STYLE defs
963 ostr << fill;
964
965 }
966 else {
967
968 // Elements "own" CTEXT will be always output first -> check for problems, if other elements added first.
969 // ostr << data.ctext;
970
971 if (data.isScript()){
972 ostr << data.ctext; // let < and > pass through
973 }
974 else {
975 ostr << data.ctext; // let < and > pass through
976 // StringTools::replace(XML::encodingMap, data.ctext, ostr); // sometimes an issue? // any time issue?
977 }
978
979 // Detect if all the children are of type CTEXT, to be rendered in a single line.
980 // Note: potential re-parsing will probably detect them as a single CTEXT element.
981 bool ALL_CTEXT = true; // (!data.ctext.empty()) || !children.empty();
982
983 for (const auto & entry: children){
984 if (!entry.second->isCText()){
985 ALL_CTEXT = false;
986 break;
987 }
988 }
989
990 // ALL_CTEXT = false;
991
992 if (ALL_CTEXT){
993 // ostr << "<!--ALL_CTEXT-->";
994 char sep=0;
995 for (const auto & entry: children){
996 if (sep){
997 ostr << sep;
998 }
999 else {
1000 sep = ' '; // consider global setting?
1001 }
1002 //ostr << entry.second->getText();
1003 //StringTools::replace(XML::encodingMap, entry.second->getText(), ostr); // any time issue?
1004 StringTools::replace(entry.second->getText(), getEntityMap(), ostr); // any time issue?
1005 // ostr << entry.second->getText();
1006 }
1007 }
1008 else {
1009 // ostr << "<!-- RECURSION -->";
1010 ostr << '\n';
1012 for (const auto & entry: children){
1013 toStream(ostr, entry.second, entry.first, indent+1); // Notice, no ++indent
1014 // "implicit" newline
1015 }
1016 ostr << fill; // for CLOSING tag
1017 }
1018
1019 }
1020
1021 // ostr << "<!-- END "<< data.getId() << ' ' << data.getTag() << '(' << data.getType() << ')' << "-->";
1022
1023 data.nodeToStream(ostr, CLOSING_TAG);
1024 ostr << '\n'; // Always after closing tag!
1025
1026 return ostr;
1027}
1028
1029
1030
1031} // drain::
1032
1033#endif /* DRAIN_XML */
1034
Two-way mapping between strings and objects of template class T.
Definition Dictionary.h:63
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
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
static void setValues(M &dst, const std::map< std::string, S > &srcMap)
Definition SmartMapTools.h:176
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:424
Definition StringBuilder.h:58
static void replace(const std::string &src, char search, char repl, std::ostream &ostr)
Replaces instances of 'search' to 'repl' in src.
Definition String.cpp:94
static void commentToStream(std::ostream &ostr, const TT... args)
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
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:156
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:146
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:234
void setStyle(const std::string &key, const std::initializer_list< V > &l)
Set style of an element.
Definition XML.h:480
const std::string & getId() const
Returns ID of this element. Hopefully a unique ID...
Definition XML.h:253
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:375
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:586
void setId(const TT &...args)
Concatenates arguments to an id.
Definition XML.h:247
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:834
static N & xmlAssignNode(N &dst, const N &src)
Assign another tree structure to another.
Definition XML.h:651
void reset()
Keep the element type but clear style, class and string data.
Definition XML.cpp:137
ReferenceMap2< FlexibleVariable > map_t
User may optionally filter attributes and CTEST with this using StringTools::replace(XML::encodingMap...
Definition XML.h:107
void setStyle(const std::string &key, const V &value)
For element/class/id, assign ...
Definition XML.h:496
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:265
void setAttribute(const std::string &key, const V &value)
"Final" implementation.
Definition XML.h:382
bool hasClass(const V &cls) const
Definition XML.h:536
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:240
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
A container for a static dictionary of enumeration values.
Definition EnumFlags.h:69
Default implementation.
Definition Type.h:541