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