1 /**
2  * yatexml.h
3  * This file is part of the YATE Project http://YATE.null.ro
4  *
5  * XML Parser and support classes
6  *
7  * Yet Another Telephony Engine - a fully featured software PBX and IVR
8  * Copyright (C) 2004-2014 Null Team
9  *
10  * This software is distributed under multiple licenses;
11  * see the COPYING file in the main directory for licensing
12  * information for this specific distribution.
13  *
14  * This use of this software may be subject to additional restrictions.
15  * See the LEGAL file in the main directory for details.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20  */
21 
22 #ifndef __YATEXML_H
23 #define __YATEXML_H
24 
25 #ifndef __cplusplus
26 #error C++ is required
27 #endif
28 
29 #include <yateclass.h>
30 
31 /**
32  * Holds all Telephony Engine related classes.
33  */
34 namespace TelEngine {
35 
36 class XmlSaxParser;
37 class XmlDomParser;
38 class XmlDeclaration;
39 class XmlFragment;
40 class XmlChild;
41 class XmlParent;
42 class XmlDocument;
43 class XmlElement;
44 class XmlComment;
45 class XmlCData;
46 class XmlText;
47 class XmlDoctype;
48 
49 
50 struct YATE_API XmlEscape {
51     /**
52      * Value to match
53      */
54     const char* value;
55 
56     /**
57      * Character replacement for value
58      */
59     char replace;
60 };
61 
62 /**
63  * A Serial Access Parser (SAX) for arbitrary XML data
64  * @short Serial Access XML Parser
65  */
66 class YATE_API XmlSaxParser : public DebugEnabler
67 {
68 public:
69     enum Error {
70 	NoError = 0,
71 	NotWellFormed,
72 	Unknown,
73 	IOError,
74 	ElementParse,
75 	ReadElementName,
76 	InvalidElementName,
77 	ReadingAttributes,
78 	CommentParse,
79 	DeclarationParse,
80 	DefinitionParse,
81 	CDataParse,
82 	ReadingEndTag,
83 	Incomplete,
84 	InvalidEncoding,
85 	UnsupportedEncoding,
86 	UnsupportedVersion,
87     };
88     enum Type {
89 	None           = 0,
90 	Text           = 1,
91 	CData          = 2,
92 	Element        = 3,
93 	Doctype        = 4,
94 	Comment        = 5,
95 	Declaration    = 6,
96 	Instruction    = 7,
97 	EndTag         = 8,
98 	Special        = 9
99     };
100 
101     /**
102      * Destructor
103      */
104     virtual ~XmlSaxParser();
105 
106     /**
107      * Get the number of bytes successfully parsed
108      * @return The number of bytes successfully parsed
109      */
offset()110     inline unsigned int offset() const
111 	{ return m_offset; }
112 
113     /**
114      * Get the row where the parser has found an error
115      * @return The row number
116      */
row()117     inline unsigned int row() const
118 	{ return m_row; }
119 
120     /**
121      * Get the column where the parser has found an error
122      * @return The column number
123      */
column()124     inline unsigned int column() const
125 	{ return m_column; }
126 
127     /**
128      * Retrieve the parser's buffer
129      * @return The parser's buffer
130      */
buffer()131     inline const String& buffer() const
132 	{ return m_buf; }
133 
134     /**
135      * Parse a given string
136      * @param data The data to parse
137      * @return True if all data was successfully parsed
138      */
139     bool parse(const char* data);
140 
141     /**
142      * Process incomplete text if the parser is completed.
143      * This method should be called to complete text after
144      *  all data was pushed into the parser
145      * @return True if all data was successfully parsed
146      */
147     bool completeText();
148 
149     /**
150      * Get the error code found while parsing
151      * @return Error code
152      */
error()153     inline Error error()
154 	{ return m_error; }
155 
156     /**
157      * Set the error code and destroys a child if error code is not NoError
158      * @param error The error found
159      * @param child Child to destroy
160      * @return False on error
161      */
162     bool setError(Error error, XmlChild* child = 0);
163 
164     /**
165      * Retrieve the error string associated with current error status
166      * @param defVal Value to return if not found
167      * @return The error string
168      */
169     inline const char* getError(const char* defVal = "Xml error")
170 	{ return getError(m_error,defVal); }
171 
172     /**
173      * @return The last xml type that we were parsing, but we have not finished
174      */
unparsed()175     inline Type unparsed()
176 	{ return m_unparsed; }
177 
178     /**
179      * Set the last xml type that we were parsing, but we have not finished
180      * @param id The xml type that we haven't finish to parse
181      */
setUnparsed(Type id)182     inline void setUnparsed(Type id)
183 	{ m_unparsed = id;}
184 
185     /**
186      * Reset error flag
187      */
188     virtual void reset();
189 
190     /**
191      * @return The internal buffer
192      */
getBuffer()193     const String& getBuffer() const
194 	{ return m_buf; }
195 
196     /**
197      * Retrieve the error string associated with a given error code
198      * @param code Code of the error to look up
199      * @param defVal Value to return if not found
200      * @return The error string
201      */
202     static inline const char* getError(int code, const char* defVal = "Xml error")
203 	{ return lookup(code,s_errorString,defVal); }
204 
205     /**
206      * Check if the given character is blank
207      * @param c The character to verify
208      * @return True if c is blank
209      */
blank(char c)210     static inline bool blank(char c)
211 	{ return (c == 0x20) || (c == 0x09) || (c == 0x0d) || (c == 0x0a); }
212 
213     /**
214      * Verify if the given character is in the range allowed
215      * to be first character from a xml tag
216      * @param ch The character to check
217      * @return True if the character is in range
218      */
219     static bool checkFirstNameCharacter(unsigned char ch);
220 
221     /**
222      * Check if the given character is in the range allowed for an xml char
223      * @param c The character to check
224      * @return True if the character is in range
225      */
226     static bool checkDataChar(unsigned char c);
227 
228     /**
229      * Verify if the given character is in the range allowed for a xml name
230      * @param ch The character to check
231      * @return True if the character is in range
232      */
233     static bool checkNameCharacter(unsigned char ch);
234 
235     /**
236      * Check if a given string is a valid xml tag name
237      * @param buf The string to check
238      * @return True if the string is a valid xml tag name
239      */
240     static bool validTag(const String& buf);
241 
242     /**
243      * XmlEscape the given text
244      * @param buf Destination buffer
245      * @param text The text to escape
246      */
247     static void escape(String& buf, const String& text);
248 
249     /**
250      * Errors dictionary
251      */
252     static const TokenDict s_errorString[];
253 
254     /**
255      * Escaped strings dictionary
256      */
257     static const XmlEscape s_escape[];
258 
259 protected:
260     /**
261      * Constructor
262      * @param name Debug name
263      */
264     XmlSaxParser(const char* name = "XmlSaxParser");
265 
266     /**
267      * Parse an instruction form the main buffer.
268      * Extracts the parsed string from buffer if returns true
269      * @return True if the instruction was parsed successfully
270      */
271     bool parseInstruction();
272 
273     /**
274      * Parse a CData section form the main buffer.
275      * Extracts the parsed string from buffer if returns true
276      * @return True if the CData section was parsed successfully
277      */
278     bool parseCData();
279 
280     /**
281      * Parse a comment form the main buffer.
282      * Extracts the parsed string from buffer if returns true
283      * @return True if the comment was parsed successfully
284      */
285     bool parseComment();
286 
287     /**
288      * Parse an element form the main buffer.
289      * Extracts the parsed string from buffer if returns true
290      * @return True if the element was parsed successfully
291      */
292     bool parseElement();
293 
294     /**
295      * Parse a declaration form the main buffer.
296      * Extracts the parsed string from buffer if returns true
297      * @return True if the declaration was parsed successfully
298      */
299     bool parseDeclaration();
300 
301     /**
302      * Helper method to classify the Xml objects starting with "<!" sequence.
303      * Extracts the parsed string from buffer if returns true
304      * @return True if a corresponding xml object was found and parsed successfully
305      */
306     bool parseSpecial();
307 
308     /**
309      * Parse an endtag form the main buffer.
310      * Extracts the parsed string from buffer if returns true
311      * @return True if the endtag was parsed successfully
312      */
313     bool parseEndTag();
314 
315     /**
316      * Parse a doctype form the main buffer.
317      * Extracts the parsed string from buffer if returns true.
318      * Warning: This is a stub implementation
319      * @return True if the doctype was parsed successfully
320      */
321     bool parseDoctype();
322 
323     /**
324      * Parse an unfinished xml object.
325      * Extracts the parsed string from buffer if returns true
326      * @return True if the object was parsed successfully
327      */
328     bool auxParse();
329 
330     /**
331      * Unescape the given text.
332      * Handled: &amp;lt; &amp;gt; &amp;apos; &amp;quot; &amp;amp;
333      *  &amp;\#DecimalNumber; &amp;\#xHexNumber;
334      * @param text The requested text to unescape
335      */
336     void unEscape(String& text);
337 
338     /**
339      * Remove blank characters from the begining of the buffer
340      */
341     void skipBlanks();
342 
343     /**
344      * Check if a character is an angle bracket
345      * @param c The character to verify
346      * @return True if c is an angle bracket
347      */
badCharacter(char c)348     inline bool badCharacter(char c)
349 	{ return c == '<' || c == '>'; }
350 
351     /**
352      * Reset the error
353      */
resetError()354     inline void resetError()
355 	{ m_error = NoError; }
356 
357     /**
358      * Reset parsed value and parameters
359      */
resetParsed()360     inline void resetParsed()
361 	{ m_parsed.clear(); m_parsed.clearParams(); }
362 
363     /**
364      * Extract the name of an element or instruction
365      * @return The extracted string or 0
366      */
367     String* extractName(bool& empty);
368 
369     /**
370      * Extract an attribute
371      * @return The attribute value or 0
372      */
373     NamedString* getAttribute();
374 
375     /**
376      * Callback method. Is called when a comment was successfully parsed.
377      * Default implementation does nothing
378      * @param text The comment content
379      */
gotComment(const String & text)380     virtual void gotComment(const String& text)
381 	{ }
382 
383     /**
384      * Callback method. Is called when an instruction was successfully parsed.
385      * Default implementation does nothing
386      * @param instr The instruction content
387      */
gotProcessing(const NamedString & instr)388     virtual void gotProcessing(const NamedString& instr)
389 	{ }
390 
391     /**
392      * Callback method. Is called when a declaration was successfully parsed.
393      * Default implementation does nothing
394      * @param decl The declaration content
395      */
gotDeclaration(const NamedList & decl)396     virtual void gotDeclaration(const NamedList& decl)
397 	{ }
398 
399     /**
400      * Callback method. Is called when a text was successfully parsed.
401      * Default implementation does nothing
402      * @param text The text content
403      */
gotText(const String & text)404     virtual void gotText(const String& text)
405 	{ }
406 
407     /**
408      * Callback method. Is called when a CData section was successfully parsed.
409      * Default implementation does nothing
410      * @param data The CData content
411      */
gotCdata(const String & data)412     virtual void gotCdata(const String& data)
413 	{ }
414 
415     /**
416      * Callback method. Is called when an element was successfully parsed.
417      * Default implementation does nothing
418      * @param element The element content
419      * @param empty True if the element does not have attributes
420      */
gotElement(const NamedList & element,bool empty)421     virtual void gotElement(const NamedList& element, bool empty)
422 	{ }
423 
424     /**
425      * Callback method. Is called when a end tag was successfully parsed.
426      * Default implementation does nothing
427      * @param name The end tag name
428      */
endElement(const String & name)429     virtual void endElement(const String& name)
430 	{ }
431 
432     /**
433      * Callback method. Is called when a doctype was successfully parsed.
434      * Default implementation does nothing
435      * @param doc The doctype content
436      */
gotDoctype(const String & doc)437     virtual void gotDoctype(const String& doc)
438 	{ }
439 
440     /**
441      * Callback method. Is called to check if we have an incomplete element.
442      * Default implementation returns always true
443      * @return True
444      */
completed()445     virtual bool completed()
446 	{ return true; }
447 
448     /**
449      * Calls gotElement() and eset parsed on success
450      * @param list The list element and its attributes
451      * @param empty True if the element does not have attributes
452      * @return True if there is no error
453      */
454     bool processElement(NamedList& list, bool empty);
455 
456     /**
457      * Unescape text, call gotText() and reset parsed on success
458      * @param text The text to process
459      * @return True if there is no error
460      */
461     bool processText(String& text);
462 
463     /**
464      * The offset where the parser was stop
465      */
466     unsigned int m_offset;
467 
468     /**
469      * The row where the parser was stop
470      */
471     unsigned int m_row;
472 
473     /**
474      * The column where the parser was stop
475      */
476     unsigned int m_column;
477 
478     /**
479      * The error code found while parsing data
480      */
481     Error m_error;
482 
483     /**
484      * The main buffer
485      */
486     String m_buf;
487 
488     /**
489      * The parser data holder.
490      * Keeps the parsed data when an incomplete xml object is found
491      */
492     NamedList m_parsed;
493 
494     /**
495      * The last parsed xml object code
496      */
497     Type m_unparsed;
498 };
499 
500 /**
501  * Xml Parent for a Xml child
502  * @short Xml Parent
503  */
504 class YATE_API XmlParent
505 {
506 public:
507     /**
508      * Constructor
509      */
XmlParent()510     XmlParent()
511 	{ }
512 
513     /**
514      * Destructor
515      */
~XmlParent()516     virtual ~XmlParent()
517 	{ }
518 
519     /**
520      * Get an XmlDocument object from this XmlParent.
521      * Default implementation return 0
522      * @return 0
523      */
document()524     virtual XmlDocument* document()
525 	{ return 0; }
526 
527     /**
528      * Get an XmlFragment object from this XmlParent.
529      * Default implementation return 0
530      * @return 0
531      */
fragment()532     virtual XmlFragment* fragment()
533 	{ return 0; }
534 
535     /**
536      * Get an XmlElement object from this XmlParent.
537      * Default implementation return 0
538      * @return 0
539      */
element()540     virtual XmlElement* element()
541 	{ return 0; }
542 
543     /**
544      * Append a new child to this XmlParent
545      * @param child The child to append
546      * @return NoError if the child was successfully added
547      */
548     virtual XmlSaxParser::Error addChild(XmlChild* child) = 0;
549 
550     /**
551      * Append a new child of this XmlParent, release the object on failure
552      * @param child The child to append
553      * @param code Optional pointr to error code to be filled on failure
554      * @return The child on success, 0 on failure
555      */
556     inline XmlChild* addChildSafe(XmlChild* child, XmlSaxParser::Error* code = 0) {
557 	    XmlSaxParser::Error err = addChild(child);
558 	    if (err != XmlSaxParser::NoError) {
559 		TelEngine::destruct(child);
560 		if (code)
561 		    *code = err;
562 	    }
563 	    return child;
564 	}
565 
566     /**
567      * Remove a child
568      * @param child The child to remove
569      * @param delObj True to delete the object
570      * @return XmlChild pointer if found and not deleted
571      */
572     virtual XmlChild* removeChild(XmlChild* child, bool delObj = true) = 0;
573 
574     /**
575      * Reset this xml parent.
576      * Default implementation does nothing
577      */
reset()578     virtual void reset()
579 	{ }
580 
581     /**
582      * Obtain this xml parent children.
583      * Default implementation returns an empty list
584      * @return The list of children
585      */
getChildren()586     virtual const ObjList& getChildren() const
587 	{ return ObjList::empty(); }
588 
589     /**
590      * Clear this xml parent children.
591      * Default implementation does nothing
592      */
clearChildren()593     virtual void clearChildren()
594 	{  }
595 
596     /**
597      * Check if at least one child element exists
598      * @return True if this parent has at least one child
599      */
hasChildren()600     inline bool hasChildren() const
601 	{ return getChildren().skipNull() != 0; }
602 };
603 
604 /**
605  * A Document Object Model (DOM) parser for XML documents and fragments
606  * @short Document Object Model XML Parser
607  */
608 class YATE_API XmlDomParser : public XmlSaxParser
609 {
610     friend class XmlChild;
611 public:
612     /**
613      * XmlDomParser constructor
614      * @param name Debug name
615      * @param fragment True if this parser needs to parse a piece of a xml document
616      */
617     XmlDomParser(const char* name = "XmlDomParser", bool fragment = false);
618 
619     /**
620      * XmlDomParser constructor
621      * @param fragment The fragment who should keep the parsed data
622      * @param takeOwnership True to take ownership of the fragment
623      */
624     XmlDomParser(XmlParent* fragment, bool takeOwnership);
625 
626     /**
627      * Destructor
628      */
629     virtual ~XmlDomParser();
630 
631     /**
632      * Obtain an XmlDocument from the parsed data
633      * @return The XmlDocument or 0
634      */
document()635     XmlDocument* document()
636 	{ return m_data->document(); }
637 
638     /**
639      * Obtain an XmlFragment from the parsed data
640      * @return The XmlFragment or 0
641      */
fragment()642     XmlFragment* fragment()
643 	{ return m_data->fragment(); }
644 
645     /**
646      * Reset parser
647      */
648     virtual void reset();
649 
650     /**
651      * Check if the current element is the given one
652      * @param el The element to compare with
653      * @return True if they are equal
654      */
isCurrent(const XmlElement * el)655     inline bool isCurrent(const XmlElement* el) const
656 	{ return el == m_current; }
657 
658 protected:
659 
660     /**
661      * Append a xml comment in the xml tree
662      * @param text The comment content
663      */
664     virtual void gotComment(const String& text);
665 
666     /**
667      * Append a xml instruction in the xml tree
668      * @param instr The instruction content
669      */
670     virtual void gotProcessing(const NamedString& instr);
671 
672     /**
673      * Append a xml declaration in the xml tree
674      * @param decl The declaration content
675      */
676     virtual void gotDeclaration(const NamedList& decl);
677 
678     /**
679      * Append a xml text in the xml tree
680      * @param text The text content
681      */
682     virtual void gotText(const String& text);
683 
684     /**
685      * Append a xml CData in the xml tree
686      * @param data The CData content
687      */
688     virtual void gotCdata(const String& data);
689 
690     /**
691      * Append a xml element in the xml tree
692      * @param element The element content
693      * @param empty True if the element does not have attributes
694      */
695     virtual void gotElement(const NamedList& element, bool empty);
696 
697     /**
698      * Complete current element
699      * @param name The end tag name
700      */
701     virtual void endElement(const String& name);
702 
703     /**
704      * Append a xml doctype in the xml tree
705      * @param doc The doctype content
706      */
707     virtual void gotDoctype(const String& doc);
708 
709     /**
710      * Callback method. Is called to check if we have an incomplete element
711      * @return True if current element is not 0
712      */
completed()713     virtual bool completed()
714 	{ return m_current == 0; }
715 
716 private:
717     XmlElement* m_current;                   // The current xml element
718     XmlParent* m_data;                       // Main xml fragment
719     bool m_ownData;                          // The DOM owns data
720 };
721 
722 /**
723  * Xml Child for Xml document
724  * @short Xml Child
725  */
726 class YATE_API XmlChild : public GenObject
727 {
YCLASS(XmlChild,GenObject)728     YCLASS(XmlChild,GenObject)
729     friend class XmlDomParser;
730 public:
731     /**
732      * Constructor
733      */
734     XmlChild();
735 
736     /**
737      * Set this child's parent
738      * @param parent Parent of this child
739      */
740     virtual void setParent(XmlParent* parent)
741 	{ }
742 
743     /**
744      * Get a Xml element
745      * @return 0
746      */
xmlElement()747     virtual XmlElement* xmlElement()
748 	{ return 0; }
749 
750     /**
751      * Get a Xml comment
752      * @return 0
753      */
xmlComment()754     virtual XmlComment* xmlComment()
755 	{ return 0; }
756 
757     /**
758      * Get a Xml CData
759      * @return 0
760      */
xmlCData()761     virtual XmlCData* xmlCData()
762 	{ return 0; }
763 
764     /**
765      * Get a Xml text
766      * @return 0
767      */
xmlText()768     virtual XmlText* xmlText()
769 	{ return 0; }
770 
771     /**
772      * Get a Xml declaration
773      * @return 0
774      */
xmlDeclaration()775     virtual XmlDeclaration* xmlDeclaration()
776 	{ return 0; }
777 
778     /**
779      * Get a Xml doctype
780      * @return 0
781      */
xmlDoctype()782     virtual XmlDoctype* xmlDoctype()
783 	{ return 0; }
784 
785     /**
786      * Replaces all ${paramname} with the corresponding parameters
787      * @param params List of parameters
788      */
replaceParams(const NamedList & params)789     virtual void replaceParams(const NamedList& params)
790 	{}
791 };
792 
793 
794 /**
795  * Xml Declaration for Xml document
796  * @short Xml Declaration
797  */
798 class YATE_API XmlDeclaration : public XmlChild
799 {
800     YCLASS(XmlDeclaration,XmlChild)
801 public:
802     /**
803      * Constructor
804      * @param version XML version attribute
805      * @param enc Encoding attribute
806      */
807     XmlDeclaration(const char* version = "1.0", const char* enc = "utf-8");
808 
809     /**
810      * Constructor
811      * @param decl Declaration attributes
812      */
813     XmlDeclaration(const NamedList& decl);
814 
815     /**
816      * Copy constructor
817      * @param orig Original XmlDeclaration
818      */
819     XmlDeclaration(const XmlDeclaration& orig);
820 
821     /**
822      * Destructor
823      */
824     ~XmlDeclaration();
825 
826     /**
827      * Obtain the tag name and attributes list
828      * @return The declaration
829      */
getDec()830     inline const NamedList& getDec() const
831 	{ return m_declaration; }
832 
833     /**
834      * Get the Xml declaration
835      * @return This object
836      * Reimplemented from XmlChild
837      */
xmlDeclaration()838     virtual XmlDeclaration* xmlDeclaration()
839 	{ return this; }
840 
841     /**
842      * Build a String from this XmlDeclaration
843      * @param dump The string where to append representation
844      * @param escape True if the attributes values need to be escaped
845      */
846     void toString(String& dump, bool escape = true) const;
847 
848 private:
849     NamedList m_declaration;                 // The declaration
850 };
851 
852 /**
853  * Xml Fragment a fragment from a Xml document
854  * @short Xml Fragment
855  */
856 class YATE_API XmlFragment : public XmlParent
857 {
858 public:
859 
860     /**
861      * Constructor
862      */
863     XmlFragment();
864 
865     /**
866      * Copy constructor
867      * @param orig Original XmlFragment
868      */
869     XmlFragment(const XmlFragment& orig);
870 
871     /**
872      * Destructor
873      */
874     virtual ~XmlFragment();
875 
876     /**
877      * Get an Xml Fragment
878      * @return This
879      */
fragment()880     virtual XmlFragment* fragment()
881 	{ return this; }
882 
883     /**
884      * Get the list of children
885      * @return The children list
886      */
getChildren()887     virtual const ObjList& getChildren() const
888 	{ return m_list; }
889 
890     /**
891      * Append a new xml child to this fragment
892      * @param child the child to append
893      * @return An error code if an error was detected
894      */
895     virtual XmlSaxParser::Error addChild(XmlChild* child);
896 
897     /**
898      * Reset this Xml Fragment
899      */
900     virtual void reset();
901 
902     /**
903      * Remove the first child from list and returns it
904      * @return XmlChild pointer or 0
905      */
pop()906     inline XmlChild* pop()
907 	{ return static_cast<XmlChild*>(m_list.remove(false)); }
908 
909     /**
910      * Remove the first XmlElement from list and returns it if completed
911      * @return XmlElement pointer or 0 if no XmlElement is found or the first one is not completed
912      */
913     XmlElement* popElement();
914 
915     /**
916      * Remove a child. Reset the parent of not deleted xml element
917      * @param child The child to remove
918      * @param delObj True to delete the object
919      * @return XmlChild pointer if found and not deleted
920      */
921     virtual XmlChild* removeChild(XmlChild* child, bool delObj = true);
922 
923     /**
924      * Clear the list of children
925      */
clearChildren()926     virtual void clearChildren()
927 	{ m_list.clear(); }
928 
929     /**
930      * Copy other fragment into this one
931      * @param other Fragment to copy
932      * @param parent Optional parent to set in copied children
933      */
934     void copy(const XmlFragment& other, XmlParent* parent = 0);
935 
936     /**
937      * Build a String from this XmlFragment
938      * @param dump The string where to append representation
939      * @param escape True if the attributes values need to be escaped
940      * @param indent Spaces for output
941      * @param origIndent Original indent
942      * @param completeOnly True to build only if complete
943      * @param auth Optional list of tag and attribute names to be replaced with '***'. This
944      *  parameter can be used when the result will be printed to output to avoid printing
945      *  authentication data to output. The array must end with an empty string
946      * @param parent Optional parent element whose tag will be searched in the auth list
947      */
948     void toString(String& dump, bool escape = true, const String& indent = String::empty(),
949 	const String& origIndent = String::empty(), bool completeOnly = true,
950 	const String* auth = 0, const XmlElement* parent = 0) const;
951 
952     /**
953      * Replaces all ${paramname} in fragment's children with the corresponding parameters
954      * @param params List of parameters
955      */
956     void replaceParams(const NamedList& params);
957 
958     /**
959      * Find a completed xml element in a list
960      * @param list The list to search for the element
961      * @param name Optional element tag to match
962      * @param ns Optional element namespace to match
963      * @param noPrefix True to compare the tag without namespace prefix, false to
964      *  include namespace prefix when comparing the given tag.
965      *  This parameter is ignored if name is 0 or ns is not 0
966      * @return XmlElement pointer or 0 if not found
967      */
968     static XmlElement* findElement(ObjList* list, const String* name, const String* ns,
969 	bool noPrefix = true);
970 
971 private:
972     ObjList m_list;                    // The children list
973 };
974 
975 /**
976  * Xml Document
977  * @short Xml Document
978  */
979 class YATE_API XmlDocument : public XmlParent
980 {
981 public:
982 
983     /**
984      * The Constructor
985      */
986     XmlDocument();
987 
988     /**
989      * Destructor
990      */
991     virtual ~XmlDocument();
992 
993     /**
994      * Get an Xml Document
995      * @return This
996      */
document()997     virtual XmlDocument* document()
998 	{ return this; }
999 
1000     /**
1001      * Append a new child to this document.
1002      * Set the root to an XML element if not already set. If we already have a completed root
1003      *  the element will be added to the root, otherwise an error will be returned.
1004      * If we don't have a root non xml elements (other then text) will be added the list
1005      *  of elements before root
1006      * @param child The child to append
1007      * @return An error code if an error was detected
1008      */
1009     virtual XmlSaxParser::Error addChild(XmlChild* child);
1010 
1011     /**
1012      * Retrieve the document declaration
1013      * @return XmlDeclaration pointer or 0 if not found
1014      */
1015     XmlDeclaration* declaration() const;
1016 
1017     /**
1018      * Retrieve XML fragment outside the root element
1019      * @param before True to retrieve the fragment holding children before root element,
1020      *  false to retrieve children after root
1021      * @return Requested fragment's reference
1022      */
getFragment(bool before)1023     inline const XmlFragment& getFragment(bool before) const
1024 	{ return before ? m_beforeRoot : m_afterRoot; }
1025 
1026     /**
1027      * Retrieve the root element
1028      * @param completed True to retrieve the root element if is not completed
1029      * @return Root pointer or 0 if not found or is not completed
1030      */
1031     XmlElement* root(bool completed = false) const;
1032 
1033     /**
1034      * Take the root element from the document
1035      * @param completed True to retrieve the root element if is not completed
1036      * @return Root pointer or 0 if not found or is not completed
1037      */
1038     inline XmlElement* takeRoot(bool completed = false)
1039     {
1040 	XmlElement* r = root(completed);
1041 	if (r)
1042 	    m_root = 0;
1043 	return r;
1044     }
1045 
1046     /**
1047      * Reset this Xml Document
1048      */
1049     virtual void reset();
1050 
1051     /**
1052      * Remove a child
1053      * @param child The child to remove
1054      * @param delObj True to delete the object
1055      * @return XmlChild pointer if found and not deleted
1056      */
1057     virtual XmlChild* removeChild(XmlChild* child, bool delObj = true)
1058 	{ return m_beforeRoot.removeChild(child,delObj); }
1059 
1060     /**
1061      * Load this document from data stream and parse it.
1062      * @param in The input stream
1063      * @param error Optional pointer to data to be filled with error if IOError is returned
1064      * @return Parser error (NoError on success)
1065      */
1066     virtual XmlSaxParser::Error read(Stream& in, int* error = 0);
1067 
1068     /**
1069      * Write this document to a data stream.
1070      * A indent + n * origIndent will be added before each xml child,
1071      *  where n is the imbrication level, starting with 0.
1072      * A indent + (n + 1) * origIndent will be added before each attribute
1073      * @param out The output stream
1074      * @param escape True if the attributes values need to be escaped
1075      * @param indent Line indent
1076      * @param origIndent Original indent
1077      * @param completeOnly True to build only if complete
1078      * @return Written bytes, negative on error
1079      */
1080     virtual int write(Stream& out, bool escape = true,
1081 	const String& indent = String::empty(), const String& origIndent = String::empty(),
1082 	bool completeOnly = true) const;
1083 
1084     /**
1085      * Load a file an parse it
1086      * Reset the document
1087      * @param file The file to load
1088      * @param error Pointer to data to be filled with file error if IOError is returned
1089      * @return Parser error (NoError on success)
1090      */
1091     XmlSaxParser::Error loadFile(const char* file, int* error = 0);
1092 
1093     /**
1094      * Save this xml document in the specified file. Create a new fle if not found.
1095      * Truncate an existing one
1096      * @param file The file to save or will be used the file used on load
1097      * @param escape True if the attributes values need to be escaped
1098      * @param indent Spaces for output
1099      * @param completeOnly True to build only if complete
1100      * @param eoln End of line chars. Set it to NULL to ignore it. Empty string will be replaced by CR/LF
1101      * @return 0 on success, error code on failure
1102      */
1103     int saveFile(const char* file = 0, bool escape = true,
1104 	const String& indent = String::empty(), bool completeOnly = true,
1105 	const char* eoln = "\r\n") const;
1106 
1107     /**
1108      * Build a String from this XmlDocument
1109      * @param dump The string where to append representation
1110      * @param escape True if the attributes values need to be escaped
1111      * @param indent Spaces for output
1112      * @param origIndent Original indent
1113      */
1114     void toString(String& dump, bool escape = true, const String& indent = String::empty(),
1115 	const String& origIndent = String::empty()) const;
1116 
1117     /**
1118      * Replaces all ${paramname} in document's components with the corresponding parameters
1119      * @param params List of parameters
1120      */
1121     void replaceParams(const NamedList& params);
1122 
1123 private:
1124     XmlElement* m_root;                  // The root element
1125     XmlFragment m_beforeRoot;            // XML children before root (declaration ...)
1126     String m_file;                       // The file name used on load
1127     XmlFragment m_afterRoot;             // XML children after root (comments, empty text)
1128 };
1129 
1130 
1131 /**
1132  * Xml Element from a Xml document
1133  * @short Xml Element
1134  */
1135 
1136 class YATE_API XmlElement : public XmlChild, public XmlParent
1137 {
1138     YCLASS(XmlElement,XmlChild)
1139 public:
1140     /**
1141      * Constructor
1142      * @param element The NamedList name represent the element name and the param the attributes
1143      * @param empty False if has children
1144      * @param parent The parent of this element
1145      */
1146     XmlElement(const NamedList& element, bool empty, XmlParent* parent = 0);
1147 
1148     /**
1149      * Constructor. Creates a new complete and empty element
1150      * @param name The name of the element
1151      * @param complete False to build an incomplete element
1152      */
1153     XmlElement(const char* name, bool complete = true);
1154 
1155     /**
1156      * Constructor. Create a new element with a text child
1157      * @param name The name of the element
1158      * @param value Element text child value
1159      * @param complete False to build an incomplete element
1160      */
1161     XmlElement(const char* name, const char* value, bool complete = true);
1162 
1163     /**
1164      * Copy constructor
1165      * @param orig Original XmlElement
1166      */
1167     XmlElement(const XmlElement& orig);
1168 
1169     /**
1170      * Destructor
1171      */
1172     virtual ~XmlElement();
1173 
1174     /**
1175      * Retrieve the element's tag
1176      * @return The element's tag
1177      */
tag()1178     inline const char* tag() const
1179 	{ return m_element; }
1180 
1181     /**
1182      * Check if this element must be processed in the default namespace (its tag is not prefixed)
1183      * @return True if this element must be processed in the default namespace
1184      */
isDefaultNs()1185     inline bool isDefaultNs() const
1186 	{ return m_prefixed == 0; }
1187 
1188     /**
1189      * Retrieve the element's tag unprefixed (namespace prefix removed)
1190      * @return The element's tag unprefixed
1191      */
unprefixedTag()1192     inline const String& unprefixedTag() const
1193 	{ return m_prefixed ? m_prefixed->name() : static_cast<const String&>(m_element); }
1194 
1195     /**
1196      * Set element's unprefixed tag, don't change namespace prefix
1197      * @param s New element's tag
1198      */
1199     void setUnprefixedTag(const String& s);
1200 
1201     /**
1202      * Retrieve the element's tag (without prefix)
1203      * @return Element tag
1204      */
getTag()1205     inline const String& getTag() const
1206 	{ return m_prefixed ? m_prefixed->name() : static_cast<const String&>(m_element); }
1207 
1208     /**
1209      * Retrieve the element's tag (without prefix) and namespace
1210      * @param tag Pointer to element tag
1211      * @param ns Pointer to element's namespace (may be 0 for unprefixed tags)
1212      * @return True if a namespace was found for the element tag or the tag is not prefixed
1213      */
1214     bool getTag(const String*& tag, const String*& ns) const;
1215 
1216     /**
1217      * Get an XmlElement from this XmlChild
1218      * @return This object
1219      */
xmlElement()1220     virtual XmlElement* xmlElement()
1221 	{ return this; }
1222 
1223     /**
1224      * Get an XmlElement from this XmlParent
1225      * @return This object
1226      */
element()1227     virtual XmlElement* element()
1228 	{ return this; }
1229 
1230     /**
1231      * Append a new child of this element
1232      * @param child The child to append
1233      */
1234     virtual XmlSaxParser::Error addChild(XmlChild* child);
1235 
1236     /**
1237      * Remove a child
1238      * @param child The child to remove
1239      * @param delObj True to delete the object
1240      * @return XmlChild pointer if found and not deleted
1241      */
1242     virtual XmlChild* removeChild(XmlChild* child, bool delObj = true);
1243 
1244     /**
1245      * Notification for this element that is complete
1246      */
setCompleted()1247     virtual void setCompleted()
1248 	{ m_complete = true; }
1249 
1250     /**
1251      * @return True if this element is completed
1252      */
completed()1253     inline bool completed() const
1254 	{ return m_complete; }
1255 
1256     /**
1257      * @return True if this element is empty
1258      */
empty()1259     inline bool empty() const
1260 	{ return m_empty; }
1261 
1262     /**
1263      * Retrieve an XmlElement parent of this one
1264      * @return XmlElement pointer or 0
1265      */
parent()1266     inline XmlElement* parent() const
1267 	{ return m_parent ? m_parent->element() : 0; }
1268 
1269     /**
1270      * @return The parent of this element
1271      */
getParent()1272     virtual XmlParent* getParent()
1273 	{ return m_parent; }
1274 
1275     /**
1276      * Set this element's parent. Update inherited namespaces
1277      * @return The parent of this element
1278      */
1279     virtual void setParent(XmlParent* parent);
1280 
1281     /**
1282      * @return The name of this element
1283      */
getName()1284     virtual const String& getName() const
1285 	{ return m_element; }
1286 
1287     /**
1288      * @return The held element
1289      */
getElement()1290     virtual const NamedList& getElement() const
1291 	{ return m_element; }
1292 
1293     /**
1294      * Helper method to obtain the children list
1295      * @return The children list
1296      */
getChildren()1297     inline const ObjList& getChildren() const
1298 	{ return m_children.getChildren(); }
1299 
1300     /**
1301      * Helper method to clear the children list
1302      */
clearChildren()1303     inline void clearChildren()
1304 	{ return m_children.clearChildren(); }
1305 
1306     /**
1307      * Retrieve the list of inherited namespaces
1308      * @return The list of inherited namespaces (or 0)
1309      */
inheritedNs()1310     inline const NamedList* inheritedNs() const
1311 	{ return m_inheritedNs; }
1312 
1313     /**
1314      * Set inherited namespaces from a given element. Reset them anyway
1315      * @param xml The source element used to set inherited namespaces
1316      * @param inherit Copy element's inherited namespaces if it doesn't have a parent
1317      */
1318     void setInheritedNs(const XmlElement* xml = 0, bool inherit = true);
1319 
1320     /**
1321      * Add inherited namespaces from a list
1322      * @param list The list of namespaces
1323      */
1324     void addInheritedNs(const NamedList& list);
1325 
1326     /**
1327      * Extract the first child element
1328      * @return XmlElement pointer or 0
1329      */
pop()1330     inline XmlElement* pop() {
1331 	    XmlElement* x = findFirstChild();
1332 	    if (!(x && x->completed()))
1333 		return 0;
1334 	    m_children.removeChild(x,false);
1335 	    return x;
1336 	}
1337 
1338     /**
1339      * Retrieve the element tag
1340      * @return The element tag
1341      */
toString()1342     virtual const String& toString() const
1343 	{ return m_element; }
1344 
1345     /**
1346      * Build (append to) a String from this XmlElement
1347      * @param dump The destination string
1348      * @param escape True if the attributes values need to be escaped
1349      * @param indent Spaces for output
1350      * @param origIndent Original indent
1351      * @param completeOnly True to build only if complete
1352      * @param auth Optional list of tag and attribute names to be replaced with '***'. This
1353      *  parameter can be used when the result will be printed to output to avoid printing
1354      *  authentication data to output. The array must end with an empty string
1355      */
1356     void toString(String& dump, bool escape = true, const String& indent = String::empty(),
1357 	const String& origIndent = String::empty(), bool completeOnly = true,
1358 	const String* auth = 0) const;
1359 
1360     /**
1361      * Find the first XmlElement child of this XmlElement
1362      * @param name Optional name of the child
1363      * @param ns Optional child namespace
1364      * @param noPrefix True to compare the tag without namespace prefix, false to
1365      *  include namespace prefix when comparing the given tag.
1366      *  This parameter is ignored if name is 0 or ns is not 0
1367      * @return The first child element meeting the requested conditions
1368      */
1369     inline XmlElement* findFirstChild(const String* name = 0, const String* ns = 0,
1370 	bool noPrefix = true) const
1371 	{ return XmlFragment::findElement(getChildren().skipNull(),name,ns,noPrefix); }
1372 
1373     /**
1374      * Find the first XmlElement child of this XmlElement
1375      * @param name Name of the child
1376      * @param ns Optional child namespace
1377      * @param noPrefix True to compare the tag without namespace prefix, false to
1378      *  include namespace prefix when comparing the given tag.
1379      *  This parameter is ignored if name is 0 or ns is not 0
1380      * @return The first child element meeting the requested conditions
1381      */
1382     inline XmlElement* findFirstChild(const String& name, const String* ns = 0,
1383 	bool noPrefix = true) const
1384 	{ return XmlFragment::findElement(getChildren().skipNull(),&name,ns,noPrefix); }
1385 
1386     /**
1387      * Finds next XmlElement child of this XmlElement
1388      * @param prev Previous child
1389      * @param name Optional name of the child
1390      * @param ns Optional child namespace
1391      * @param noPrefix True to compare the tag without namespace prefix, false to
1392      *  include namespace prefix when comparing the given tag.
1393      *  This parameter is ignored if name is 0 or ns is not 0
1394      * @return The next found child if prev exists else the first
1395      */
1396     inline XmlElement* findNextChild(const XmlElement* prev = 0, const String* name = 0,
1397 	const String* ns = 0, bool noPrefix = true) const {
1398 	    if (!prev)
1399 		return findFirstChild(name,ns,noPrefix);
1400 	    ObjList* start = getChildren().find(prev);
1401 	    return start ? XmlFragment::findElement(start->skipNext(),name,ns,noPrefix) : 0;
1402 	}
1403 
1404     /**
1405      * Finds next XmlElement child of this XmlElement
1406      * @param name Name of the child
1407      * @param prev Previous child
1408      * @param ns Optional child namespace
1409      * @param noPrefix True to compare the tag without namespace prefix, false to
1410      *  include namespace prefix when comparing the given tag.
1411      *  This parameter is ignored if name is 0 or ns is not 0
1412      * @return The next found child if prev exists else the first
1413      */
1414     inline XmlElement* findNextChild(const String& name, const XmlElement* prev = 0,
1415 	const String* ns = 0, bool noPrefix = true) const
1416         { return findNextChild(prev,&name,ns,noPrefix); }
1417 
1418     /**
1419      * Retrieve a child's text
1420      * @param name Name (tag) of the child
1421      * @param ns Optional child namespace
1422      * @param noPrefix True to compare the tag without namespace prefix, false to
1423      *  include namespace prefix when comparing the given tag.
1424      *  This parameter is ignored ns is not 0
1425      * @return Pointer to child's text, 0 if the child was not found
1426      */
1427     inline const String* childText(const String& name, const String* ns = 0,
1428 	bool noPrefix = true) const {
1429 	    XmlElement* c = findFirstChild(&name,ns,noPrefix);
1430 	    return c ? &(c->getText()) : 0;
1431 	}
1432 
1433     /**
1434      * Get first XmlChild of this XmlElement
1435      * @return The first XmlChild found.
1436      */
1437      XmlChild* getFirstChild();
1438 
1439     /**
1440      * @return The first XmlText found in this XmlElement children
1441      */
1442     const String& getText() const;
1443 
1444     /**
1445      * Set text for first XmlText element found in this XmlElement's children
1446      * If child text element does not exist, create it and append it to the element's children.
1447      * @param text Text to set to the XmlElement. If null, the first found XmlText element
1448      *  will be deleted.
1449      * @return The set XmlText if text was set, null if an XmlText was deleted
1450      */
1451     XmlText* setText(const char* text);
1452 
1453     /**
1454      * Add a text child
1455      * @param text Non empty text to add
1456      */
1457     void addText(const char* text);
1458 
1459     /**
1460      * Retrieve the list of attributes
1461      * @return Element attributes
1462      */
attributes()1463     inline const NamedList& attributes() const
1464 	{ return m_element; }
1465 
1466     /**
1467      * Copy element attributes to a list of parameters
1468      * @param list Destination list
1469      * @param prefix Prefix to be added to each attribute name
1470      * @return The number of attributes added to the destination list
1471      */
1472     unsigned int copyAttributes(NamedList& list, const String& prefix) const;
1473 
1474     /**
1475      * Set element attributes from a list of parameters
1476      * @param list List of attributes
1477      * @param prefix Add only the attributes that start with this prefix. =
1478      *  If NULL, it will set as attributes the whole parameter list
1479      * @param skipPrefix Skip over the prefix when building attribute name
1480      */
1481     void setAttributes(NamedList& list, const String& prefix, bool skipPrefix = true);
1482 
1483     /**
1484      * Add or replace an attribute
1485      * @param name Attribute name
1486      * @param value Attribute value
1487      */
setAttribute(const String & name,const char * value)1488     inline void setAttribute(const String& name, const char* value)
1489 	{ m_element.setParam(name,value); }
1490 
1491     /**
1492      * Add or replace an attribute. Clears it if value is empty
1493      * @param name Attribute name
1494      * @param value Attribute value
1495      */
setAttributeValid(const String & name,const char * value)1496     inline void setAttributeValid(const String& name, const char* value) {
1497 	    if (!TelEngine::null(value))
1498 		m_element.setParam(name,value);
1499 	    else
1500 		removeAttribute(name);
1501 	}
1502 
1503     /**
1504      * Obtain an attribute value for the given name
1505      * @param name The name of the attribute
1506      * @return Attribute value
1507      */
attribute(const String & name)1508     inline const char* attribute(const String& name) const
1509 	{ return m_element.getValue(name); }
1510 
1511     /**
1512      * Obtain an attribute value for the given name
1513      * @param name The name of the attribute
1514      * @return String pointer or 0 if not found
1515      */
getAttribute(const String & name)1516     inline String* getAttribute(const String& name) const
1517 	{ return m_element.getParam(name); }
1518 
1519     /**
1520      * Check if the element has an attribute with a requested value
1521      * @param name The name of the attribute
1522      * @param value The value to check
1523      * @return True if the element has an attribute with the requested value
1524      */
hasAttribute(const String & name,const String & value)1525     inline bool hasAttribute(const String& name, const String& value) const {
1526 	    String* a = getAttribute(name);
1527 	    return a && *a == value;
1528 	}
1529 
1530     /**
1531      * Remove an attribute
1532      * @param name Attribute name
1533      */
removeAttribute(const String & name)1534     inline void removeAttribute(const String& name)
1535 	{ m_element.clearParam(name); }
1536 
1537     /**
1538      * Retrieve the element's namespace
1539      * @return Element's namespace or 0 if not found
1540      */
xmlns()1541     inline String* xmlns() const {
1542 	    if (!m_prefixed)
1543 		return xmlnsAttribute(s_ns);
1544 	    return xmlnsAttribute(s_nsPrefix + *m_prefixed);
1545 	}
1546 
1547     /**
1548      * Retrieve a namespace attribute. Search in parent or inherited for it
1549      * @return String pointer or 0 if not found
1550      */
1551     String* xmlnsAttribute(const String& name) const;
1552 
1553     /**
1554      * Verify if this element belongs to the given namespace
1555      * @param ns The namespace to compare with
1556      * @return True if this element belongs to the given namespace
1557      */
hasXmlns(const String & ns)1558     inline bool hasXmlns(const String& ns) const {
1559 	    const String* x = xmlns();
1560 	    return x && *x == ns;
1561 	}
1562 
1563     /**
1564      * Set the element's namespace
1565      * @param name The namespace name (element prefix). Can be the default
1566      *  namespace attribute name (empty means the default one)
1567      * @param addAttr True to add a non empty, not repeating, namespace attribute to the list
1568      * @param value Namespace value (ignored if addAttr is false)
1569      * @return True on success, false if another namespace exists with the same value
1570      */
1571     bool setXmlns(const String& name = String::empty(), bool addAttr = false,
1572 	const String& value = String::empty());
1573 
1574     /**
1575      * Replaces all ${paramname} in element's attributes and children with the
1576      *  corresponding parameters
1577      * @param params List of parameters
1578      */
1579     virtual void replaceParams(const NamedList& params);
1580 
1581     /**
1582      * Check if a string represents a namespace attribute name
1583      * @param str The string to check
1584      * @return True if the given string is the default namespace attribute name or
1585      *  a namespace attribute name prefix
1586      */
isXmlns(const String & str)1587     static inline bool isXmlns(const String& str)
1588 	{ return str == s_ns || str.startsWith(s_nsPrefix); }
1589 
1590     /**
1591      * Build an XML element from a list parameter.
1592      * Parameter name will be set in a 'name' attribute.
1593      * Parameter value will be set in a 'value' attribute
1594      * Handle NamedPointer parameters carrying DataBlock, NamedList and
1595      *  XmlElement objects (a 'type' attribute is added to the created element).
1596      *  DataBlock: Encode using BASE64 and add it as element text
1597      *  NamedList: The name is added as element text. The function is called
1598      *   again for each list parameter
1599      *  XmlElement: Added as child to newly created element
1600      * @param param The parameter to convert
1601      * @param tag XmlElement tag
1602      * @param copyXml True to copy XmlElement objects instead of just remove
1603      *  them from the parameter
1604      * @return XmlElement pointer or 0 on failure
1605      */
1606     static XmlElement* param2xml(NamedString* param, const String& tag,
1607 	bool copyXml = false);
1608 
1609     /**
1610      * Build a list parameter from xml element
1611      * See @ref param2xml for more info
1612      * @param xml The XML element to process
1613      * @param tag Child XmlElement tag to handle
1614      * @param copyXml True to copy XmlElement objects instead of just remove
1615      *  them from parent
1616      * @return NamedString pointer or 0 on failure
1617      */
1618     static NamedString* xml2param(XmlElement* xml, const String* tag,
1619 	bool copyXml = false);
1620 
1621     /**
1622      * Build and add list parameters from XML element children.
1623      * Each parameter will be taken from 'name' and 'value' attributes.
1624      * See @ref param2xml for more info
1625      * @param list Destination list
1626      * @param parent The XML element to process
1627      * @param tag Child XmlElement tag to handle
1628      * @param copyXml True to copy XmlElement objects instead of just remove
1629      *  them from parent
1630      */
1631     static void xml2param(NamedList& list, XmlElement* parent, const String* tag,
1632 	bool copyXml = false);
1633 
1634     /**
1635      * Default namespace attribute name
1636      */
1637     static const String s_ns;
1638 
1639     /**
1640      * Namespace attribute name perfix
1641      */
1642     static const String s_nsPrefix;
1643 
1644 private:
1645     // Set prefixed data (tag and prefix)
setPrefixed()1646     inline void setPrefixed() {
1647 	    TelEngine::destruct(m_prefixed);
1648 	    int pos = m_element.find(":");
1649 	    if (pos != -1)
1650 		m_prefixed = new NamedString(m_element.substr(pos + 1),m_element.substr(0,pos));
1651 	}
1652 
1653     XmlFragment m_children;                      // Children of this element
1654     NamedList m_element;                         // The element
1655     NamedString* m_prefixed;                     // Splitted prefixed tag (the value is the namespace prefix)
1656     XmlParent* m_parent;                         // The XmlElement who holds this element
1657     NamedList* m_inheritedNs;                    // Inherited namespaces (if parent is 0)
1658     bool m_empty;                                // True if this element does not have any children
1659     bool m_complete;                             // True if the end element tag war reported
1660 };
1661 
1662 /**
1663  * A Xml Comment from Xml document
1664  * @short Xml Comment
1665  */
1666 class YATE_API XmlComment : public XmlChild
1667 {
1668     YCLASS(XmlComment,XmlChild)
1669 public:
1670     /**
1671      * Constructor
1672      * @param comm The comment content
1673      */
1674     XmlComment(const String& comm);
1675 
1676     /**
1677      * Copy constructor
1678      * @param orig Original XmlComment
1679      */
1680     XmlComment(const XmlComment& orig);
1681 
1682     /**
1683      * Destructor
1684      */
1685     virtual ~XmlComment();
1686 
1687     /**
1688      * Get the text contained by this comment
1689      * @return The comment
1690      */
getComment()1691     inline const String& getComment() const
1692 	{ return m_comment; }
1693 
1694     /**
1695      * Build a String from this XmlComment
1696      * @param dump The string where to append representation
1697      * @param indent Spaces for output
1698      */
1699     void toString(String& dump, const String& indent = String::empty()) const;
1700 
1701     /**
1702      * Get the Xml comment
1703      * @return This object
1704      */
xmlComment()1705     virtual XmlComment* xmlComment()
1706 	{ return this; }
1707 
1708 private:
1709     String m_comment;                       // The comment
1710 };
1711 
1712 /**
1713  * A Xml CData from Xml document
1714  * @short Xml Declaration
1715  */
1716 class YATE_API XmlCData : public XmlChild
1717 {
1718     YCLASS(XmlCData,XmlChild)
1719 public:
1720 
1721     /**
1722      * Constructor
1723      * @param data The CData content
1724      */
1725     XmlCData(const String& data);
1726 
1727     /**
1728      * Copy constructor
1729      * @param orig Original XmlCData
1730      */
1731     XmlCData(const XmlCData& orig);
1732 
1733     /**
1734      * Destructor
1735      */
1736     virtual ~XmlCData();
1737 
1738     /**
1739      * Get the CData content
1740      * @return The content of this xml object
1741      */
getCData()1742     inline const String& getCData() const
1743 	{ return m_data;}
1744 
1745     /**
1746      * Build a String from this XmlCData
1747      * @param dump The string where to append representation
1748      * @param indent Spaces for output
1749      */
1750     void toString(String& dump, const String& indent = String::empty()) const;
1751 
1752     /**
1753      * Get the Xml CData
1754      * @return This object
1755      */
xmlCData()1756     virtual XmlCData* xmlCData()
1757 	{ return this; }
1758 
1759 private:
1760     String m_data;                        // The data
1761 };
1762 
1763 /**
1764  * A Xml Declaration for Xml document
1765  * @short Xml Declaration
1766  */
1767 class YATE_API XmlText : public XmlChild
1768 {
1769     YCLASS(XmlText,XmlChild)
1770 public:
1771     /**
1772      * Constructor
1773      * @param text The text
1774      */
1775     XmlText(const String& text);
1776 
1777     /**
1778      * Copy constructor
1779      * @param orig Original XmlText
1780      */
1781     XmlText(const XmlText& orig);
1782 
1783     /**
1784      * Destructor
1785      */
1786     virtual ~XmlText();
1787 
1788     /**
1789      * @return The text kept by this Xml Text
1790      */
getText()1791     inline const String& getText() const
1792 	{ return m_text; }
1793 
1794     /**
1795      * Set the text
1796      * @param text Text to set in this XmlText
1797      */
setText(const char * text)1798     inline void setText(const char* text)
1799 	{ m_text = text; }
1800 
1801     /**
1802      * Build a String from this XmlText
1803      * @param dump The string where to append representation
1804      * @param escape True if the text need to be escaped
1805      * @param indent Spaces for output
1806      * @param auth Optional list of tag and attribute names to be replaced with '***'. This
1807      *  parameter can be used when the result will be printed to output to avoid printing
1808      *  authentication data to output. The array must end with an empty string
1809      * @param parent Optional parent element whose tag will be searched in the auth list
1810      */
1811     void toString(String& dump, bool escape = true, const String& indent = String::empty(),
1812 	const String* auth = 0, const XmlElement* parent = 0) const;
1813 
1814     /**
1815      * Get the Xml text
1816      * @return This object
1817      */
xmlText()1818     virtual XmlText* xmlText()
1819 	{ return this; }
1820 
1821     /**
1822      * Helper method to check if the text held by this XmlText contains only spaces
1823      * @return False if the text contains non space characters.
1824      */
1825     bool onlySpaces();
1826 
1827     /**
1828      * Replaces all ${paramname} in text with the corresponding parameters
1829      * @param params List of parameters
1830      */
1831     virtual void replaceParams(const NamedList& params);
1832 
1833 private:
1834     String m_text;                        // The text
1835 };
1836 
1837 class YATE_API XmlDoctype : public XmlChild
1838 {
1839     YCLASS(XmlDoctype,XmlChild)
1840 public:
1841     /**
1842      * Constructor
1843      * @param doctype The doctype
1844      */
1845     XmlDoctype(const String& doctype);
1846 
1847     /**
1848      * Copy constructor
1849      * @param orig Original XmlDoctype
1850      */
1851     XmlDoctype(const XmlDoctype& orig);
1852 
1853     /**
1854      * Destructor
1855      */
1856     virtual ~XmlDoctype();
1857 
1858     /**
1859      * Get the doctype held by this Xml doctype
1860      * @return The content of this Xml doctype
1861      */
getDoctype()1862     inline const String& getDoctype() const
1863 	{ return m_doctype; }
1864 
1865     /**
1866      * Get the Xml doctype
1867      * @return This object
1868      */
xmlDoctype()1869     virtual XmlDoctype* xmlDoctype()
1870 	{ return this; }
1871 
1872     /**
1873      * Build a String from this XmlDoctype
1874      * @param dump The string where to append representation
1875      * @param indent Spaces for output
1876      */
1877     void toString(String& dump, const String& indent = String::empty()) const;
1878 
1879 private:
1880     String m_doctype;                          // The document type
1881 };
1882 
1883 }; // namespace TelEngine
1884 
1885 #endif /* __YATEXML_H */
1886 
1887 /* vi: set ts=8 sw=4 sts=4 noet: */
1888