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
74 static
75 const std::map<char,std::string> encodingMap;
76
78
80
83 template <class T2, class ...T3>
84 inline
85 bool typeIs(const T2 & arg, const T3... args) const {
86 if (type == static_cast<intval_t>(arg)){
87 return true;
88 }
89 else {
90 return typeIs(args...);
91 }
92 };
93
94protected:
95
96 inline
97 bool typeIs() const {
98 return false;
99 };
100
101protected:
102
103 intval_t type = XML::UNDEFINED;
104
105 // String, still easily allowing numbers through set("id", ...)
106 std::string id;
107 // Consider either/or
108 std::string url;
109public:
110 std::string ctext;
111
112 // Could be templated, behind Static?
113 static int nextID;
114
115 inline
116 static int getCount(){
117 return nextID;
118 }
119
120
121 inline
122 bool isUndefined() const {
123 return type == UNDEFINED;
124 }
125
126 inline
127 bool isComment() const {
128 return type == COMMENT;
129 }
130
131 inline
132 bool isCText() const {
133 return type == CTEXT;
134 }
135
136 inline
137 bool isStyle() const {
138 return type == STYLE;
139 }
140
141 inline
142 bool isScript() const {
143 return type == SCRIPT;
144 }
145
147 virtual
148 bool isSingular() const;
149
151 virtual
152 bool isExplicit() const;
153
155
159 virtual
160 void clear();
161
163
167 inline
168 void reset(){
169 clear();
170 type = UNDEFINED;
171 }
172
174
177 inline
178 void setId(){
179 link("id", id);
180 }
181
183 inline
184 void setId(const std::string & s){
185 link("id", id = s);
186 }
187
189 template <char C='\0', typename ...TT>
190 inline
191 void setId(const TT & ...args) {
192 link("id", id = drain::StringBuilder<C>(args...));
193 }
194
196 inline
197 const std::string & getId() const {
198 return id;
199 }
200
201
203
207 template <class ...T>
208 inline
209 void setComment(const T & ...args) {
210 this->clear(); // what if also uncommenting needed?
211 // this->clearClasses();
212 type = COMMENT;
213 setText(args...);
214 }
215
217
222 virtual // redef shows variadic args, below?
223 void setText(const std::string & s);
224
225 template <class ...T>
226 void setText(const T & ...args) {
227 setText(StringBuilder<>(args...).str()); // str() to avoid infinite loop
228 }
229
230 virtual inline
231 const std::string & getText() const {
232 return ctext;
233 }
234
235 inline
236 const std::string & getUrl(){
237 return url;
238 }
239
240 inline
241 void setUrl(const std::string & s){
242 url = s;
243 // ctext = s;
244 }
245
246 template <class ...T>
247 inline
248 void setName(const T & ...args){
249 setAttribute("data-name", drain::StringBuilder<>(args...));
250 }
251
252
253 // ---------------- Attributes ---------------
254
255 virtual inline // shadows - consider virtual
256 bool empty() const {
257 return map_t::empty();
258 }
259
260 inline
261 const map_t & getAttributes() const {
262 return *this;
263 };
264
265 // Maybe controversial. Helps importing sets of variables.
266 inline
267 map_t & getAttributes(){
268 return *this;
269 };
270
271 // Rename getAttribute?
272 inline
273 const drain::FlexibleVariable & get(const std::string & key) const {
274 return (*this)[key];
275 }
276
277 // Rename getAttribute?
278 inline
279 drain::FlexibleVariable & get(const std::string & key){
280 return (*this)[key];
281 }
282
283
284 // Rename getAttribute?
285 template <class V>
286 inline
287 V get(const std::string & key, const V & defaultValue) const {
288 return map_t::get(key, defaultValue);
289 }
290
291 inline
292 std::string get(const std::string & key, const char * defaultValue) const {
293 return map_t::get(key, defaultValue);
294 }
295
297 // But otherways confusing?
298 virtual inline
299 void setAttribute(const std::string & key, const std::string &value){
300 (*this)[key] = value;
301 }
302
304 // But otherways confusing?
305 virtual inline
306 void setAttribute(const std::string & key, const char *value){
307 (*this)[key] = value; // -> handleString()
308 }
309
311 template <class V>
312 inline
313 void setAttribute(const std::string & key, const V & value){
314 (*this)[key] = value; // -> handleString()
315 }
316
317
318 inline
319 void removeAttribute(const std::string & s){
320 iterator it = this->find(s);
321 if (it != this->end()){
322 this->erase(it);
323 }
324 }
325
326
327 // ------------------ Style ---------------
328
329protected:
330
331 StyleXML style;
332
333public:
334
335 inline
336 const StyleXML & getStyle() const {
337 return style;
338 }
339
340 inline
341 void setStyle(const StyleXML & s){
342 style.clear();
343 SmartMapTools::setValues(style, s);
344 }
345
346 void setStyle(const std::string & value){
347 drain::Logger mout(__FILE__, __FUNCTION__);
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");
351 }
352 else if (type == STYLE){
353 mout.reject<LOG_WARNING>("not setting style for STYLE elem: ", value); // , *this);
354 }
355 else {
356 SmartMapTools::setValues(style, value, ';', ':', "; \t\n"); // sep, equal, trim (also ';' ?)
357 }
358 }
359
360 inline
361 void setStyle(const char *value){
362 setStyle(std::string(value));
363 }
364
365 inline
366 void setStyle(const std::string & key, const std::string & value){
367 drain::Logger mout(__FILE__, __FUNCTION__);
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");
371 }
372 else if (type == STYLE){
373 mout.reject<LOG_WARNING>("not setting style for STYLE elem: ", value); // , *this);
374 }
375 else {
376 this->style[key] = value;
377 }
378 }
379
380
382
388 template <class V>
389 inline
390 void setStyle(const std::string & key, const std::initializer_list<V> &l){
391 // const std::initializer_list<Variable::init_pair_t > &l
392 if (type == STYLE){ // typeIs(STYLE) fails
393 drain::Logger mout(__FILE__, __FUNCTION__);
394 mout.warn("Setting style of STYLE? initializer_list<", drain::TypeName<V>::str(), "> = ", sprinter(l)); // , StyleXML::styleLineLayout ?
395 }
396 this->style[key] = l;
397 }
398
399
401
404 template <class V>
405 inline
406 void setStyle(const std::string & key, const V & value){
407
408 if (type == STYLE){
409 drain::Logger(__FILE__, __FUNCTION__).reject<LOG_WARNING>("Setting style of STYLE: ", key, "=", value);
410 }
411 else {
412 this->style[key] = value;
413 }
414 }
415
416 inline
417 void setStyle(const std::initializer_list<std::pair<const char *,const drain::Variable> > &args){
419 }
420
421 /*
422 void setStyle( const std::initializer_list<std::pair<const char *,const char *> > & args){
423 drain::SmartMapTools::setValues(style, args);
424 }
425 */
426
427 /*
428 template <class S>
429 inline
430 void setStyle(const S &value){
431 drain::Logger mout(__FILE__, __FUNCTION__);
432 mout.error("unsupported type ", drain::TypeName<S>::str(), " for value: ", typeid(value));
433 }
434 */
435
436
437protected:
438
439 // ------------------ Style Class ---------------
440
441 ClassListXML classList;
442
443public:
444
445 const ClassListXML & getClasses() const {
446 return classList;
447 }
448
449 template <typename ... TT>
450 inline
451 void addClass(const TT &... args) {
452 classList.add(args...);
453 }
454
458 template <class V>
459 inline
460 bool hasClass(const V & cls) const {
461 return classList.has(cls);
462 }
463
464 inline
465 void removeClass(const std::string & s) {
466 classList.remove(s);
467 }
468
469 inline
470 void clearClasses(){
471 classList.clear();
472 }
473
474
475 virtual
476 void specificAttributesToStream(std::ostream & ostr) const;
477
478
479 enum tag_display_mode {
480 FLEXIBLE_TAG = 0, // <TAG>...</TAG> or <TAG/>
481 OPENING_TAG= 1, // <TAG>
482 CLOSING_TAG = 2, // </TAG>
483 EMPTY_TAG = OPENING_TAG | CLOSING_TAG, // element has no descendants: <hr/>
484 NON_EMPTY_TAG, // opening and closing tags must appear, even when empty: <script></script>
485 };
486
487
488 virtual
489 std::ostream & nodeToStream(std::ostream & ostr, tag_display_mode mode=EMPTY_TAG) const = 0;
490
491// ----------------- Static utilities for derived classes ----------------------
492
493
494 template <class TR>
495 static
496 std::ostream & toStream(std::ostream & ostr, const TR & tree, const std::string & defaultTag="ELEM", int indent=0);
497
498
499 template <class V>
500 static inline
501 void xmlAttribToStream(std::ostream &ostr, const std::string & key, const V &value){
502 //StringTools::replace(XML::encodingMap, data.ctext, ostr);
503 //ostr << ' ' << key << '=' << '"' << value << '"'; // << ' ';
504 ostr << ' ';
506 ostr << '=' << '"';
508 ostr << '"';
509 //<< key << '=' << '"' << value << '"'; // << ' ';
510 }
511
513
516 template <typename TX>
517 static inline
518 TX & xmlAssign(TX & dst, const TX & src){
519
520 if (&src != &dst){
521 dst.clear();
522 // also dst->clear();
523 dst->setType(src->getType());
524 dst->setText(src->ctext); //CTXX
525 dst->getAttributes() = src->getAttributes();
526 }
527
528 return dst;
529 }
530
532
535 template <typename TX>
536 static inline
537 TX & xmlAssign(TX & dst, const typename TX::xml_node_t & src){
538
539 xmlAssignNode(dst.data, src);
540 /*
541 if (&src != &dst.data){
542 dst->clear(); NOW reset()
543 dst->getAttributes().importMap(src.getAttributes());
544 dst->setStyle(src.getStyle());
545 dst->setText(src.ctext);
546 }
547 */
548 return dst;
549 }
550
552
557 template <typename X>
558 static inline
559 X & xmlAssignNode(X & dst, const X & src){
560
561 if (&src != &dst){
562 //dst.clear(); // clear attributes,
563 dst.reset(); // clear attributes, style, cstring and type.
564 dst.setType(src.getType()); // important: creates links!
565 dst.getAttributes().importMap(src.getAttributes());
566 dst.setStyle(src.getStyle());
567 // dst.setText(src.ctext); // wrong! set type to CTEXT
568 dst.ctext = src.ctext;
569 }
570
571 return dst;
572 }
573
575
578 template <typename TX, typename V>
579 static inline
580 TX & xmlAssign(TX & tree, const V & arg){
581 tree->set(arg);
582 return tree;
583 }
584
586
589 template <typename TX>
590 static
591 //T & xmlAssign(T & tree, std::initializer_list<std::pair<const char *,const char *> > l){
592 TX & xmlAssign(TX & tree, std::initializer_list<std::pair<const char *,const Variable> > l){
593
594 switch (static_cast<intval_t>(tree->getType())){
595 case STYLE:
596 for (const auto & entry: l){
597 TX & elem = tree[entry.first];
598 elem->setType(STYLE_SELECT);
599 drain::SmartMapTools::setValues(elem->getAttributes(), entry.second, ';', ':', std::string(" \t\n"));
600 }
601 break;
602 case UNDEFINED:
603 tree->setType(STYLE_SELECT);
604 // no break
605 case STYLE_SELECT:
606 default:
607 tree->set(l);
608 break;
609 }
610
611 return tree;
612 };
613
614 // UNDER CONSTRUCTION!
616
621 template <typename TX>
622 static inline // NOT YET as template specification of xmlAssign(...)
623 TX & xmlAssignString(TX & tree, const std::string & s){
624 if (tree->isUndefined()){
625 tree->setType(CTEXT);
626 }
627 tree->ctext = s;
628 return tree;
629 /*
630 if (tree->isCText()){
631 tree->setText(s);
632 return tree;
633 }
634 else if (tree->isUndefined()){
635 tree->setType(CTEXT);
636 tree->setText(s);
637 return tree;
638 }
639 else {
640 for (auto & entry: tree){
641 if (entry.second->isCText()){
642 entry.second->setText(s);
643 return entry.second;
644 }
645 }
646 // drain::Logger(__FILE__, __FUNCTION__).error("Assign string...");
647 TX & child = tree.addChild();
648 child->setType(CTEXT);
649 child->setText(s);
650 return child;
651 }
652 */
653 }
654
655 template <typename TX>
656 static inline // NOT YET as template specification of xmlAssign(...)
657 TX & xmlAppendString(TX & tree, const std::string & s){
658 if (tree->isCText()){
659 tree->ctext += s;
660 return tree;
661 }
662 else if (tree->isUndefined()){
663 tree->setType(CTEXT);
664 // tree->setText(s);
665 tree->ctext += s;
666 return tree;
667 }
668 else {
669 // drain::Logger(__FILE__, __FUNCTION__).error("Assign string...");
670 TX & child = tree.addChild();
671 child->setType(CTEXT);
672 child->setText(s);
673 return child;
674 }
675 }
676
678
682 template <typename TX>
683 static inline
684 TX & xmlSetType(TX & tree, const typename TX::node_data_t::xml_tag_t & type){
685 tree->setType(type);
686 return tree;
687 }
688
689
695 template <typename T>
696 static
697 T & xmlAddChild(T & tree, const std::string & key){
698 typename T::node_data_t::xml_tag_t type = xmlRetrieveDefaultType(tree.data);
699
700 if (!key.empty()){
701 return tree[key](type);
702 }
703 else {
704 std::stringstream k; // ("elem");
705 k << "elem"; // number with 4 digits overwrites this?
706 k.width(3); // consider static member prefix
707 k.fill('0');
708 k << tree.getChildren().size();
709 return tree[k.str()](type);
710 }
711 }
712
713 template <typename N>
714 static
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()){
719 return (it->second);
720 }
721 else {
722 return static_cast<typename N::xml_tag_t>(0);
723 }
724 }
725
726 /*
727 template <typename T>
728 static
729 T & xmlGuessType(const typename T::node_data_t & parentNode, T & child){
730 typedef typename T::node_data_t::xml_default_elem_map_t map_t;
731 const typename map_t::const_iterator it = T::node_data_t::xml_default_elems.find(parentNode.getNativeType());
732 if (it != T::node_data_t::xml_default_elems.end()){
733 child->setType(it->second);
734 drain::Logger(__FILE__, __FUNCTION__).experimental<LOG_WARNING>("Default type set: ", child->getTag());
735 }
736 return child;
737 }
738 */
739
740
741
742};
743
744
745template <class TR>
746std::ostream & XML::toStream(std::ostream & ostr, const TR & tree, const std::string & defaultTag, int indent){
747
748 drain::Logger mout(__FILE__,__FUNCTION__);
749
750 const typename TR::container_t & children = tree.getChildren();
751
752 // const XML & data = tree.data; // template type forcing, keep here for programming aid.
753 const typename TR::node_data_t & data = tree.data; // template used
754
755 tag_display_mode mode = EMPTY_TAG;
756
757 if (data.isCText()){ // this can be true only at root, and rarely so...? (because recursive call not reached, if ctext)
758 data.nodeToStream(ostr, mode);
759 // ostr << "<!--TX-->";
760 return ostr;
761 }
762
763 if (!data.ctext.empty()){
764 // mout.warn("Non-CTEXT-elem with ctext: <", data.getTag(), " id='", data.getId(), "' ...>, text='", data.ctext, "'");
765 if (data.isSingular()){
766 // mout.warn("Skipping CTEXT of a singular element <", tree->getTag(), " id='", data.getId(), "' ...> , CTEXT: '", data.ctext, "'");
767 mode = EMPTY_TAG;
768 }
769 else {
770 mode = OPENING_TAG;
771 }
772 }
773
774 if (!children.empty()){
775 mode = OPENING_TAG;
776 if (data.isSingular()){
777 mout.warn("Singular (hence normally empty) element <", tree->getTag(), " id='", data.getId(), "' ...> has ", children.size(), " children?");
778 }
779 }
780
781 // mout.attention("Hey! ", TypeName<TR>::str(), " with ", TypeName<typename TR::node_data_t>::str(), "Explicit ", data.isExplicit(), " or implicit ", data.isSingular());
782 if (data.isExplicit()){ // explicit
783 mode = OPENING_TAG;
784 }
785 else if (data.isSingular()){ // <br/> <hr/>
786 mode = EMPTY_TAG;
787 }
788 // Hence, is flexible, "bimodal", supports empty and open-close mode.
789
790 // Indent
791 // std::fill_n(std::ostream_iterator<char>(ostr), 2*indent, ' ');
792 std::string fill(2*indent, ' ');
793 ostr << fill;
794 data.nodeToStream(ostr, mode);
795
796 if (mode == EMPTY_TAG){
797 //ostr << "<!--ET-->";
798 ostr << '\n';
799 return ostr;
800 }
801 else if (data.isStyle()){
802 // https://www.w3.org/TR/xml/#sec-cdata-sect
803 // ostr << "<![CDATA[ \n";
804 // ostr << "<!-- STYLE -->"; WRONG!
805
806 if (!data.ctext.empty()){
807 // TODO: indent
808 ostr << fill << data.ctext;
809 StyleXML::commentToStream(ostr, " TEXT ");
810 ostr << '\n';
811 }
812
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 ";
816 Sprinter::toStream(ostr, data.getAttributes()); //, StyleXML::styleRecordLayout
817 ostr << " /--> *" << "/" << '\n';
818 }
819
820 if (!data.style.empty()){
821 ostr << fill;
822 StyleXML::commentToStream(ostr, "STYLE OBJ");
823 ostr << '\n';
824 for (const auto & attr: data.style){
825 ostr << fill << " ";
826 Sprinter::pairToStream(ostr, attr, StyleXML::styleRecordLayout); // {" :;"}
827 //attr.first << ':' attr.first << ':';
828 ostr << '\n';
829 }
830 // ostr << fill << "}\n";
831 // Sprinter::sequenceToStream(ostr, entry.second->getAttributes(), StyleXML::styleRecordLayoutActual);
832 // ostr << '\n';
833 }
834 ostr << '\n';
835
836 ostr << fill;
837 StyleXML::commentToStream(ostr, "style ELEMS");
838 ostr << '\n';
839
840 for (const auto & entry: tree.getChildren()){
841
842 if (entry.second->isComment()){
843 // StringTools::replace();
844 ostr << fill << "/* "<< entry.second->ctext << " */" << '\n';
845 // XML::toStream(ostr, entry.second, defaultTag, indent); // indent not used?
846 continue;
847 }
848
849 if (!entry.second->ctext.empty()){
850 //ostr << fill << "<!-- elem("<< entry.first << ") ctext /-->" << '\n';
851 ostr << fill << " " << entry.first << " {" << entry.second->ctext << "} /* CTEXT */ \n";
852 }
853
854 if (!entry.second->getAttributes().empty()){
855 ostr << fill << " " << entry.first << " {\n";
856 for (const auto & attr: entry.second->getAttributes()){
857 ostr << fill << " ";
858 ostr << attr.first << ':' << attr.second << ';';
859 ostr << '\n';
860 }
861 ostr << fill << " }\n";
862 ostr << '\n';
863 }
864
865 }
866 ostr << "\n"; // end CTEXT
867 // ostr << " ]]>\n"; // end CTEXT
868 // end STYLE defs
869 ostr << fill;
870
871 }
872 else {
873
874 // Elements "own" CTEXT will be always output first -> check for problems, if other elements added first.
875 // ostr << data.ctext;
876
877 if (data.isScript()){
878 ostr << data.ctext; // let < and > pass through
879 }
880 else {
881 StringTools::replace(XML::encodingMap, data.ctext, ostr); // any time issue?
882 }
883
884 // Detect if all the children are of type CTEXT, to be rendered in a single line.
885 // Note: potential re-parsing will probably detect them as a single CTEXT element.
886 bool ALL_CTEXT = true; // (!data.ctext.empty()) || !children.empty();
887
888 for (const auto & entry: children){
889 if (!entry.second->isCText()){
890 ALL_CTEXT = false;
891 break;
892 }
893 }
894
895 // ALL_CTEXT = false;
896
897 if (ALL_CTEXT){
898 // ostr << "<!--ALL_CTEXT-->";
899 char sep=0;
900 for (const auto & entry: children){
901 if (sep){
902 ostr << sep;
903 }
904 else {
905 sep = ' '; // consider global setting?
906 }
907 //ostr << entry.second->getText();
908 StringTools::replace(XML::encodingMap, entry.second->getText(), ostr); // any time issue?
909 // ostr << entry.second->getText();
910 }
911 }
912 else {
913 // ostr << "<!-- RECURSION -->";
914 ostr << '\n';
916 for (const auto & entry: children){
917 toStream(ostr, entry.second, entry.first, indent+1); // Notice, no ++indent
918 // "implicit" newline
919 }
920 ostr << fill; // for CLOSING tag
921 }
922
923 }
924
925 // ostr << "<!-- END "<< data.getId() << ' ' << data.getTag() << '(' << data.getType() << ')' << "-->";
926
927 data.nodeToStream(ostr, CLOSING_TAG);
928 ostr << '\n'; // Always after closing tag!
929
930 return ostr;
931}
932
933
934
935} // drain::
936
937#endif /* DRAIN_XML */
938
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
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:420
Definition StringBuilder.h:58
static std::string replace(const std::string &src, const std::string &from, const std::string &to)
Definition String.h:96
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
Definition Type.h:542