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: &lt; &gt; &apos; &quot; &amp; 333 * &\#DecimalNumber; &\#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