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
57
58
60class XML : protected ReferenceMap2<FlexibleVariable> {
61public:
62
63 typedef int intval_t;
64
65 // TODO:
66 // static const intval_t flag_OPEN = 128;
67 // static const intval_t flag_TEXT = 256;
68 static const intval_t UNDEFINED = 0;
69 static const intval_t COMMENT = 1; // || flag_TEXT
70 static const intval_t CTEXT = 2; // || flag_TEXT
71 static const intval_t SCRIPT = 3; // || flag_EXPLICIT || flag_TEXT
72 static const intval_t STYLE = 4; // || flag_EXPLICIT
73 static const intval_t STYLE_SELECT = 5;
74
75 enum entity_t {
76 AMPERSAND = '&',
77 LESS_THAN = '<',
78 EQUAL_TO = '=',
79 GREATER_THAN = '>',
80 NONBREAKABLE_SPACE = ' ',
81 QUOTE = '"',
82 CURLY_LEFT = '{',
83 CURLY_RIGHT = '}',
84 // ---
85 TAB = '\t',
86 NEWLINE = '\n',
87 // ---
88 DEGREE = 176,
89 };
90
91 /* Variants of entity map */
92
94 static
95 const std::map<char,std::string> & getKeyConversionMap();
96
98 static
99 const std::map<char,std::string> & getAttributeConversionMap();
100
102 static
103 const std::map<char,std::string> & getCTextConversionMap();
104
105
107 // OLD static const std::map<char,std::string> encodingMap;
108
110
111
112
113public:
114
115 inline
116 XML(){};
117
118 inline
119 XML(const XML &){
120
121 };
122
123 template <class T> // "final"
124 void setType(const T &t){ // DANGER, without cast?
125 const intval_t t2 = static_cast<intval_t>(t);
126 if (type != t2){
127 reset();
128 type = t2; // also UNDEFINED ok here
129 handleType(); // NOTE: problems, if copy constructor etc. calls setType on a base class – trying to link future members
130 }
131 // handleType(static_cast<T>(t)); REMOVED 2025/09
132 // in derived classes, eg. drain::image::BaseGDAL
133 // warning: case value ‘...’ not in enumerated type
134 }
135
136 // Consider this later, for user-defined (not enumerated) tag types.
137 // virtual
138 // void setType(const std::string & type);
139
140
141 inline
142 const intval_t & getType() const {
143 return type;
144 };
145
147 inline
148 bool typeIsSet() const {
149 return type != UNDEFINED;
150 };
151
153
156 template <class T2, class ...T3>
157 inline
158 bool typeIs(const T2 & arg, const T3... args) const {
159 if (type == static_cast<intval_t>(arg)){
160 return true;
161 }
162 else {
163 return typeIs(args...);
164 }
165 };
166
167
168 std::string ctext;
169
170 // Could be templated, behind Static?
171 static int nextID;
172
173 inline
174 static int getCount(){
175 return nextID;
176 }
177
178
179 inline
180 bool isUndefined() const {
181 return type == UNDEFINED;
182 }
183
184 inline
185 bool isComment() const {
186 return type == COMMENT;
187 }
188
189 inline
190 bool isCText() const {
191 return type == CTEXT;
192 }
193
194 inline
195 bool isStyle() const {
196 return type == STYLE;
197 }
198
199 inline
200 bool isScript() const {
201 return type == SCRIPT;
202 }
203
205 virtual
206 bool isSingular() const;
207
209 virtual
210 bool isExplicit() const;
211
213
221 void reset();
232
235 inline
236 void setId(){
237 link("id", id);
238 }
239
241 inline
242 void setId(const std::string & s){
243 link("id", id = s);
244 }
245
247 template <char C='\0', typename ...TT>
248 inline
249 void setId(const TT & ...args) {
250 link("id", id = drain::StringBuilder<C>(args...));
251 }
252
254 inline
255 const std::string & getId() const {
256 return id;
257 }
258
259
261
265 template <class ...T>
266 inline
267 void setComment(const T & ...args) {
268 this->clear(); // what if also uncommenting needed?
269 // this->clearClasses();
270 type = COMMENT;
271 setText(args...);
272 }
273
275
280 virtual // redef shows variadic args, below?
281 void setText(const std::string & s);
282
283 template <class ...T>
284 void setText(const T & ...args) {
285 setText(StringBuilder<>(args...).str()); // str() to avoid infinite loop
286 }
287
288 template <class ...T>
289 void setTextSafe(const T & ...args) {
290 std::string dst;
291 StringTools::replace(StringBuilder<>(args...).str(), getCTextConversionMap(), dst); // str() to avoid infinite loop
292 setText(dst);
293 //setText(StringTools::replace(m, StringBuilder<>(args...).str(), ctext)); // str() to avoid infinite loop
294 }
295
296 virtual inline
297 const std::string & getText() const {
298 return ctext;
299 }
300
301 inline
302 const std::string & getUrl(){
303 return url;
304 }
305
306 inline
307 void setUrl(const std::string & s){
308 url = s;
309 // ctext = s;
310 }
311
312 template <class ...T>
313 inline
314 void setName(const T & ...args){
315 setAttribute("data-name", drain::StringBuilder<>(args...).str());
316 }
317
318 inline
319 const FlexibleVariable & getName() const {
320 return (*this)["data-name"];
321 }
322
323
324 // ---------------- Attributes ---------------
325
326 virtual inline // shadows - consider virtual
327 bool empty() const {
328 return map_t::empty();
329 }
330
331 inline
332 const map_t & getAttributes() const {
333 return *this;
334 };
335
336 // Maybe controversial. Helps importing sets of variables.
337 inline
338 map_t & getAttributes(){
339 return *this;
340 };
341
342 // Rename getAttribute?
343 inline
344 const drain::FlexibleVariable & get(const std::string & key) const {
345 return (*this)[key];
346 }
347
348 // Rename getAttribute?
349 inline
350 drain::FlexibleVariable & get(const std::string & key){
351 return (*this)[key];
352 }
353
354
355 // Rename getAttribute?
356 template <class V>
357 inline
358 V get(const std::string & key, const V & defaultValue) const {
359 return map_t::get(key, defaultValue);
360 }
361
362 inline
363 std::string get(const std::string & key, const char * defaultValue) const {
364 return map_t::get(key, defaultValue);
365 }
366
368 // But otherways confusing?
369 virtual inline
370 void setAttribute(const std::string & key, const std::string &value){
371 (*this)[key] = value;
372 }
373
375 // But otherways confusing?
376 virtual inline
377 void setAttribute(const std::string & key, const char *value){
378 (*this)[key] = value; // -> handleString()
379 }
380
382 template <class V>
383 inline
384 void setAttribute(const std::string & key, const V & value){
385 (*this)[key] = value; // -> handleString()
386 }
387
388
389 inline
390 void removeAttribute(const std::string & s){
391 iterator it = this->find(s);
392 if (it != this->end()){
393 this->erase(it);
394 }
395 }
396
397
398
399protected:
400
401 inline
402 bool typeIs() const {
403 return false;
404 };
405
406 intval_t type = XML::UNDEFINED;
407
408 // String, still easily allowing numbers through set("id", ...)
409 std::string id;
410 // Consider either/or
411 std::string url;
412
413 virtual inline
414 void handleType(){}; // = 0;
415
416
417public:
418
419 // ------------------ Style ---------------
420
421protected:
422
423 StyleXML style;
424
425public:
426
427 inline
428 const StyleXML & getStyle() const {
429 return style;
430 }
431
432 inline
433 void setStyle(const StyleXML & s){
434 style.clear();
435 MapTools::setValues(style, s);
436 }
437
438 void setStyle(const std::string & value){
439 drain::Logger mout(__FILE__, __FUNCTION__);
440 if (type == UNDEFINED){
441 mout.reject<LOG_WARNING>("setting style for UNDEFINED elem: ", value);
442 mout.unimplemented<LOG_WARNING>("future option: set type to STYLE_SELECT");
443 }
444 else if (type == STYLE){
445 mout.reject<LOG_WARNING>("not setting style for STYLE elem: ", value); // , *this);
446 }
447 else {
448 MapTools::setValues(style, value, ';', ':', "; \t\n"); // sep, equal, trim (also ';' ?)
449 }
450 }
451
452 inline
453 void setStyle(const char *value){
454 setStyle(std::string(value));
455 }
456
457 inline
458 void setStyle(const std::string & key, const std::string & value){
459 drain::Logger mout(__FILE__, __FUNCTION__);
460 if (type == UNDEFINED){
461 mout.reject<LOG_WARNING>("setting style for UNDEFINED elem: ", key, '=', value);
462 mout.unimplemented<LOG_WARNING>("future option: set type to STYLE_SELECT");
463 }
464 else if (type == STYLE){
465 mout.reject<LOG_WARNING>("not setting style for STYLE elem: ", value); // , *this);
466 }
467 else {
468 this->style[key] = value;
469 }
470 }
471
472
474
480 template <class V>
481 inline
482 void setStyle(const std::string & key, const std::initializer_list<V> &l){
483 // const std::initializer_list<Variable::init_pair_t > &l
484 if (type == STYLE){ // typeIs(STYLE) fails
485 drain::Logger mout(__FILE__, __FUNCTION__);
486 mout.warn("Setting style of STYLE? initializer_list<", drain::TypeName<V>::str(), "> = ", sprinter(l)); // , StyleXML::styleLineLayout ?
487 }
488 this->style[key] = l;
489 }
490
491
493
496 template <class V>
497 inline
498 void setStyle(const std::string & key, const V & value){
499
500 if (type == STYLE){
501 drain::Logger(__FILE__, __FUNCTION__).reject<LOG_WARNING>("Setting style of STYLE: ", key, "=", value);
502 }
503 else {
504 this->style[key] = value;
505 }
506 }
507
508 inline
509 void setStyle(const std::initializer_list<std::pair<const char *,const drain::Variable> > &args){
510 drain::SmartMapTools::setValues(style, args);
511 }
512
513
514
515protected:
516
517 // ------------------ Style Class ---------------
518
519 ClassListXML classList;
520
521public:
522
523 const ClassListXML & getClasses() const {
524 return classList;
525 }
526
527 template <typename ... TT>
528 inline
529 void addClass(const TT &... args) {
530 classList.add(args...);
531 }
532
536 template <class V>
537 inline
538 bool hasClass(const V & cls) const {
539 return classList.has(cls);
540 }
541
542 inline
543 void removeClass(const std::string & s) {
544 classList.remove(s);
545 }
546
547 inline
548 void clearClasses(){
549 classList.clear();
550 }
551
552
553 virtual
554 void specificAttributesToStream(std::ostream & ostr) const;
555
556
557 enum tag_display_mode {
558 FLEXIBLE_TAG = 0, // <TAG>...</TAG> or <TAG/>
559 OPENING_TAG= 1, // <TAG>
560 CLOSING_TAG = 2, // </TAG>
561 EMPTY_TAG = OPENING_TAG | CLOSING_TAG, // element has no descendants: <hr/>
562 NON_EMPTY_TAG, // opening and closing tags must appear, even when empty: <script></script>
563 };
564
565
566 virtual
567 std::ostream & nodeToStream(std::ostream & ostr, tag_display_mode mode=EMPTY_TAG) const = 0;
568
569
570
571 template <class TR>
572 static
573 std::ostream & toStream(std::ostream & ostr, const TR & tree, const std::string & defaultTag="ELEM", int indent=0);
574
576
578 static
579 const std::map<char,std::string> & getEntityMap();
580
582
586 // core utility (not to be external)
587 template <class V>
588 static inline
589 void xmlAttribToStream(std::ostream &ostr, const std::string & key, const V &value){
590 //StringTools::replace(XML::encodingMap, data.ctext, ostr);
591 //ostr << ' ' << key << '=' << '"' << value << '"'; // << ' ';
592
593 static const std::map<char,char> keyMap = {
594 {' ','_'},
595 {'"','_'},
596 {'=','_'},
597 };
598 ostr << ' ';
599 StringTools::replace(key, keyMap, ostr); // XML::encodingMap
600 //StringTools::replace(getEntityMap(), key, ostr); // XML::encodingMap
601
602 static const std::map<char,std::string> valueMap = {
603 {entity_t::QUOTE, "'"},
604 {entity_t::LESS_THAN,"(("},
605 {entity_t::GREATER_THAN,"))"},
606 };
607 ostr << '=' << '"';
608 StringTools::replace(value, valueMap, ostr); // XML::encodingMap
609 //StringTools::replace(getEntityMap(), value, ostr); // XML::encodingMap
610 ostr << '"';
611 //<< key << '=' << '"' << value << '"'; // << ' ';
612 }
613
614
616
621 template <typename N>
622 static inline
623 N & xmlAssignNode(N & dst, const N & src){
624
625 if (&src != &dst){
626 //dst.clear(); // clear attributes,
627 //if (!dst.typeIs(src.getNativeType())){
628 if (dst.getType() != src.getType()){
629 dst.reset(); // clear attributes, style, cstring and type.
630 // Warning: does not create links.
631 dst.setType(src.getType());
632 }
633 dst.getAttributes().importMap(src.getAttributes());
634 dst.setStyle(src.getStyle());
635 // dst.setText(src.ctext); // wrong! set type to CTEXT
636 dst.ctext = src.ctext;
637 }
638
639 return dst;
640 }
641
642
643
644 /*
645 UNUSED!
646 template <typename T>
647 static
648 T & xmlGuessType(const typename T::node_data_t & parentNode, T & child){
649 typedef typename T::node_data_t::xml_default_elem_map_t map_t;
650 const typename map_t::const_iterator it = T::node_data_t::xml_default_elems.find(parentNode.getNativeType());
651 if (it != T::node_data_t::xml_default_elems.end()){
652 child->setType(it->second);
653 drain::Logger(__FILE__, __FUNCTION__).experimental<LOG_WARNING>("Default type set: ", child->getTag());
654 }
655 return child;
656 }
657 */
658
659
660
661};
662
663
664template <>
666
667DRAIN_ENUM_OSTREAM(XML::entity_t);
668
669template <class TR>
670std::ostream & XML::toStream(std::ostream & ostr, const TR & tree, const std::string & defaultTag, int indent){
671
672 drain::Logger mout(__FILE__,__FUNCTION__);
673
674 const typename TR::container_t & children = tree.getChildren();
675
676 // const XML & data = tree.data; // template type forcing, keep here for programming aid.
677 const typename TR::node_data_t & data = tree.data; // template used
678
679 tag_display_mode mode = EMPTY_TAG;
680
681 if (data.isCText()){ // this can be true only at root, and rarely so...? (because recursive call not reached, if ctext)
682 data.nodeToStream(ostr, mode);
683 // ostr << "<!--TX-->";
684 return ostr;
685 }
686
687 if (!data.ctext.empty()){
688 // mout.warn("Non-CTEXT-elem with ctext: <", data.getTag(), " id='", data.getId(), "' ...>, text='", data.ctext, "'");
689 if (data.isSingular()){
690 // mout.warn("Skipping CTEXT of a singular element <", tree->getTag(), " id='", data.getId(), "' ...> , CTEXT: '", data.ctext, "'");
691 mode = EMPTY_TAG;
692 }
693 else {
694 mode = OPENING_TAG;
695 }
696 }
697
698 if (!children.empty()){
699 mode = OPENING_TAG;
700 if (data.isSingular()){
701 mout.warn("Singular (hence normally empty) element <", tree->getTag(), " id='", data.getId(), "' ...> has ", children.size(), " children?");
702 }
703 }
704
705 // mout.attention("Hey! ", TypeName<TR>::str(), " with ", TypeName<typename TR::node_data_t>::str(), "Explicit ", data.isExplicit(), " or implicit ", data.isSingular());
706 if (data.isExplicit()){ // explicit
707 mode = OPENING_TAG;
708 }
709 else if (data.isSingular()){ // <br/> <hr/>
710 mode = EMPTY_TAG;
711 }
712 // Hence, is flexible, "bimodal", supports empty and open-close mode.
713
714 // Indent
715 // std::fill_n(std::ostream_iterator<char>(ostr), 2*indent, ' ');
716 std::string fill(2*indent, ' ');
717 ostr << fill;
718 data.nodeToStream(ostr, mode);
719
720 if (mode == EMPTY_TAG){
721 //ostr << "<!--ET-->";
722 ostr << '\n';
723 return ostr;
724 }
725 else if (data.isStyle()){
726 // https://www.w3.org/TR/xml/#sec-cdata-sect
727 // ostr << "<![CDATA[ \n";
728 // ostr << "<!-- STYLE -->"; WRONG!
729
730 if (!data.ctext.empty()){
731 // TODO: indent
732 ostr << fill << data.ctext;
733 StyleXML::commentToStream(ostr, " TEXT ");
734 ostr << '\n';
735 }
736
737 if (!data.getAttributes().empty()){
738 mout.warn("STYLE elem ", data.getId()," contains attributes, probably meant as style: ", sprinter(data.getAttributes()));
739 ostr << "\n\t /" << "* <!-- DISCARDED attribs ";
740 Sprinter::toStream(ostr, data.getAttributes()); //, StyleXML::styleRecordLayout
741 ostr << " /--> *" << "/" << '\n';
742 }
743
744 if (!data.style.empty()){
745 ostr << fill;
746 StyleXML::commentToStream(ostr, "STYLE OBJ");
747 ostr << '\n';
748 for (const auto & attr: data.style){
749 ostr << fill << " ";
750 Sprinter::pairToStream(ostr, attr, StyleXML::styleRecordLayout); // {" :;"}
751 //attr.first << ':' attr.first << ':';
752 ostr << '\n';
753 }
754 // ostr << fill << "}\n";
755 // Sprinter::sequenceToStream(ostr, entry.second->getAttributes(), StyleXML::styleRecordLayoutActual);
756 // ostr << '\n';
757 }
758 ostr << '\n';
759
760 ostr << fill;
761 StyleXML::commentToStream(ostr, "style ELEMS");
762 ostr << '\n';
763
764 for (const auto & entry: tree.getChildren()){
765
766 if (entry.second->isComment()){
767 // StringTools::replace();
768 ostr << fill << "/* "<< entry.second->ctext << " */" << '\n';
769 // XML::toStream(ostr, entry.second, defaultTag, indent); // indent not used?
770 continue;
771 }
772
773 if (!entry.second->ctext.empty()){
774 //ostr << fill << "<!-- elem("<< entry.first << ") ctext /-->" << '\n';
775 ostr << fill << " " << entry.first << " {" << entry.second->ctext << "} /* CTEXT */ \n";
776 }
777
778 if (!entry.second->getAttributes().empty()){
779 ostr << fill << " " << entry.first << " {\n";
780 for (const auto & attr: entry.second->getAttributes()){
781 ostr << fill << " ";
782 if (attr.first == "id"){
783 StyleXML::commentToStream(ostr, "id=", attr.second);
784 // mout.suspicious("Style elem has id (", attr.second, ")");
785 }
786 else {
787 ostr << attr.first << ':' << attr.second << ';';
788 }
789 ostr << '\n';
790 }
791 ostr << fill << " }\n";
792 ostr << '\n';
793 }
794
795 }
796 ostr << "\n"; // end CTEXT
797 // ostr << " ]]>\n"; // end CTEXT
798 // end STYLE defs
799 ostr << fill;
800
801 }
802 else {
803
804 // Elements "own" CTEXT will be always output first -> check for problems, if other elements added first.
805 // ostr << data.ctext;
806
807 if (data.isScript()){
808 ostr << data.ctext; // let < and > pass through
809 }
810 else {
811 ostr << data.ctext; // let < and > pass through
812 // StringTools::replace(XML::encodingMap, data.ctext, ostr); // sometimes an issue? // any time issue?
813 }
814
815 // Detect if all the children are of type CTEXT, to be rendered in a single line.
816 // Note: potential re-parsing will probably detect them as a single CTEXT element.
817 bool ALL_CTEXT = true; // (!data.ctext.empty()) || !children.empty();
818
819 for (const auto & entry: children){
820 if (!entry.second->isCText()){
821 ALL_CTEXT = false;
822 break;
823 }
824 }
825
826 // ALL_CTEXT = false;
827
828 if (ALL_CTEXT){
829 // ostr << "<!--ALL_CTEXT-->";
830 char sep=0;
831 for (const auto & entry: children){
832 if (sep){
833 ostr << sep;
834 }
835 else {
836 sep = ' '; // consider global setting?
837 }
838 //ostr << entry.second->getText();
839 //StringTools::replace(XML::encodingMap, entry.second->getText(), ostr); // any time issue?
840 StringTools::replace(entry.second->getText(), getEntityMap(), ostr); // any time issue?
841 // ostr << entry.second->getText();
842 }
843 }
844 else {
845 // ostr << "<!-- RECURSION -->";
846 ostr << '\n';
848 for (const auto & entry: children){
849 toStream(ostr, entry.second, entry.first, indent+1); // Notice, no ++indent
850 // "implicit" newline
851 }
852 ostr << fill; // for CLOSING tag
853 }
854
855 }
856
857 // ostr << "<!-- END "<< data.getId() << ' ' << data.getTag() << '(' << data.getType() << ')' << "-->";
858
859 data.nodeToStream(ostr, CLOSING_TAG);
860 ostr << '\n'; // Always after closing tag!
861
862 return ostr;
863}
864
865
866
867} // drain::
868
869#endif /* DRAIN_XML */
870
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
static void setValues(M &dst, const std::map< std::string, S > &srcMap)
Definition MapTools.h:132
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: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 StringTools.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:158
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:148
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:236
void setStyle(const std::string &key, const std::initializer_list< V > &l)
Set style of an element.
Definition XML.h:482
const std::string & getId() const
Returns ID of this element. Hopefully a unique ID...
Definition XML.h:255
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:377
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:589
void setId(const TT &...args)
Concatenates arguments to an id.
Definition XML.h:249
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:670
static N & xmlAssignNode(N &dst, const N &src)
Assign tree node (data) to another.
Definition XML.h:623
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:109
void setStyle(const std::string &key, const V &value)
For element/class/id, assign ...
Definition XML.h:498
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:267
void setAttribute(const std::string &key, const V &value)
"Final" implementation.
Definition XML.h:384
bool hasClass(const V &cls) const
Definition XML.h:538
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:242
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 EnumUtils.h:52
Default implementation.
Definition Type.h:541