Yate
|
00001 /* 00002 * yatexml.h 00003 * This file is part of the YATE Project http://YATE.null.ro 00004 * 00005 * XML Parser and support classes 00006 * 00007 * Yet Another Telephony Engine - a fully featured software PBX and IVR 00008 * Copyright (C) 2004-2006 Null Team 00009 * 00010 * This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. 00014 * 00015 * This program is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 * GNU General Public License for more details. 00019 * 00020 * You should have received a copy of the GNU General Public License 00021 * along with this program; if not, write to the Free Software 00022 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. 00023 */ 00024 00025 #ifndef __YATEXML_H 00026 #define __YATEXML_H 00027 00028 #include <yateclass.h> 00029 00030 #ifdef _WINDOWS 00031 00032 #ifdef LIBYXML_EXPORTS 00033 #define YXML_API __declspec(dllexport) 00034 #else 00035 #ifndef LIBYXML_STATIC 00036 #define YXML_API __declspec(dllimport) 00037 #endif 00038 #endif 00039 00040 #endif /* _WINDOWS */ 00041 00042 #ifndef YXML_API 00043 #define YXML_API 00044 #endif 00045 00049 namespace TelEngine { 00050 00051 class XmlSaxParser; 00052 class XmlDomParser; 00053 class XmlDeclaration; 00054 class XmlFragment; 00055 class XmlChild; 00056 class XmlParent; 00057 class XmlDocument; 00058 class XmlElement; 00059 class XmlComment; 00060 class XmlCData; 00061 class XmlText; 00062 class XmlDoctype; 00063 00064 00065 struct YXML_API XmlEscape { 00069 const char* value; 00070 00074 char replace; 00075 }; 00076 00081 class YXML_API XmlSaxParser : public DebugEnabler 00082 { 00083 public: 00084 enum Error { 00085 NoError = 0, 00086 NotWellFormed, 00087 Unknown, 00088 IOError, 00089 ElementParse, 00090 ReadElementName, 00091 InvalidElementName, 00092 ReadingAttributes, 00093 CommentParse, 00094 DeclarationParse, 00095 DefinitionParse, 00096 CDataParse, 00097 ReadingEndTag, 00098 Incomplete, 00099 InvalidEncoding, 00100 UnsupportedEncoding, 00101 UnsupportedVersion, 00102 }; 00103 enum Type { 00104 None = 0, 00105 Text = 1, 00106 CData = 2, 00107 Element = 3, 00108 Doctype = 4, 00109 Comment = 5, 00110 Declaration = 6, 00111 Instruction = 7, 00112 EndTag = 8, 00113 Special = 9 00114 }; 00115 00119 virtual ~XmlSaxParser(); 00120 00125 inline unsigned int offset() const 00126 { return m_offset; } 00127 00132 inline unsigned int row() const 00133 { return m_row; } 00134 00139 inline unsigned int column() const 00140 { return m_column; } 00141 00146 inline const String& buffer() const 00147 { return m_buf; } 00148 00154 bool parse(const char* data); 00155 00162 bool completeText(); 00163 00168 inline Error error() 00169 { return m_error; } 00170 00177 bool setError(Error error, XmlChild* child = 0); 00178 00184 inline const char* getError(const char* defVal = "Xml error") 00185 { return getError(m_error,defVal); } 00186 00190 inline Type unparsed() 00191 { return m_unparsed; } 00192 00197 inline void setUnparsed(Type id) 00198 { m_unparsed = id;} 00199 00203 virtual void reset(); 00204 00208 const String& getBuffer() const 00209 { return m_buf; } 00210 00217 static inline const char* getError(int code, const char* defVal = "Xml error") 00218 { return lookup(code,s_errorString,defVal); } 00219 00225 static inline bool blank(char c) 00226 { return (c == 0x20) || (c == 0x09) || (c == 0x0d) || (c == 0x0a); } 00227 00234 static bool checkFirstNameCharacter(unsigned char ch); 00235 00241 static bool checkDataChar(unsigned char c); 00242 00248 static bool checkNameCharacter(unsigned char ch); 00249 00255 static bool validTag(const String& buf); 00256 00262 static void escape(String& buf, const String& text); 00263 00267 static const TokenDict s_errorString[]; 00268 00272 static const XmlEscape s_escape[]; 00273 00274 protected: 00279 XmlSaxParser(const char* name = "XmlSaxParser"); 00280 00286 bool parseInstruction(); 00287 00293 bool parseCData(); 00294 00300 bool parseComment(); 00301 00307 bool parseElement(); 00308 00314 bool parseDeclaration(); 00315 00321 bool parseSpecial(); 00322 00328 bool parseEndTag(); 00329 00336 bool parseDoctype(); 00337 00343 bool auxParse(); 00344 00351 void unEscape(String& text); 00352 00356 void skipBlanks(); 00357 00363 inline bool badCharacter(char c) 00364 { return c == '<' || c == '>'; } 00365 00369 inline void resetError() 00370 { m_error = NoError; } 00371 00375 inline void resetParsed() 00376 { m_parsed.clear(); m_parsed.clearParams(); } 00377 00382 String* extractName(bool& empty); 00383 00388 NamedString* getAttribute(); 00389 00395 virtual void gotComment(const String& text) 00396 { } 00397 00403 virtual void gotProcessing(const NamedString& instr) 00404 { } 00405 00411 virtual void gotDeclaration(const NamedList& decl) 00412 { } 00413 00419 virtual void gotText(const String& text) 00420 { } 00421 00427 virtual void gotCdata(const String& data) 00428 { } 00429 00436 virtual void gotElement(const NamedList& element, bool empty) 00437 { } 00438 00444 virtual void endElement(const String& name) 00445 { } 00446 00452 virtual void gotDoctype(const String& doc) 00453 { } 00454 00460 virtual bool completed() 00461 { return true; } 00462 00469 bool processElement(NamedList& list, bool empty); 00470 00476 bool processText(String& text); 00477 00481 unsigned int m_offset; 00482 00486 unsigned int m_row; 00487 00491 unsigned int m_column; 00492 00496 Error m_error; 00497 00501 String m_buf; 00502 00507 NamedList m_parsed; 00508 00512 Type m_unparsed; 00513 }; 00514 00519 class YXML_API XmlParent 00520 { 00521 public: 00525 XmlParent() 00526 { } 00527 00531 virtual ~XmlParent() 00532 { } 00533 00539 virtual XmlDocument* document() 00540 { return 0; } 00541 00547 virtual XmlFragment* fragment() 00548 { return 0; } 00549 00555 virtual XmlElement* element() 00556 { return 0; } 00557 00563 virtual XmlSaxParser::Error addChild(XmlChild* child) = 0; 00564 00571 virtual XmlChild* removeChild(XmlChild* child, bool delObj = true) = 0; 00572 00577 virtual void reset() 00578 { } 00579 00585 virtual const ObjList& getChildren() const 00586 { return ObjList::empty(); } 00587 00592 virtual void clearChildren() 00593 { } 00594 00599 inline bool hasChildren() const 00600 { return getChildren().skipNull() != 0; } 00601 }; 00602 00607 class YXML_API XmlDomParser : public XmlSaxParser 00608 { 00609 friend class XmlChild; 00610 public: 00616 XmlDomParser(const char* name = "XmlDomParser", bool fragment = false); 00617 00623 XmlDomParser(XmlParent* fragment, bool takeOwnership); 00624 00628 virtual ~XmlDomParser(); 00629 00634 XmlDocument* document() 00635 { return m_data->document(); } 00636 00641 XmlFragment* fragment() 00642 { return m_data->fragment(); } 00643 00647 virtual void reset(); 00648 00654 inline bool isCurrent(const XmlElement* el) const 00655 { return el == m_current; } 00656 00657 protected: 00658 00663 virtual void gotComment(const String& text); 00664 00669 virtual void gotProcessing(const NamedString& instr); 00670 00675 virtual void gotDeclaration(const NamedList& decl); 00676 00681 virtual void gotText(const String& text); 00682 00687 virtual void gotCdata(const String& data); 00688 00694 virtual void gotElement(const NamedList& element, bool empty); 00695 00700 virtual void endElement(const String& name); 00701 00706 virtual void gotDoctype(const String& doc); 00707 00712 virtual bool completed() 00713 { return m_current == 0; } 00714 00715 private: 00716 XmlElement* m_current; // The current xml element 00717 XmlParent* m_data; // Main xml fragment 00718 bool m_ownData; // The DOM owns data 00719 }; 00720 00725 class YXML_API XmlChild : public GenObject 00726 { 00727 YCLASS(XmlChild,GenObject) 00728 friend class XmlDomParser; 00729 public: 00733 XmlChild(); 00734 00739 virtual void setParent(XmlParent* parent) 00740 { } 00741 00746 virtual XmlElement* xmlElement() 00747 { return 0; } 00748 00753 virtual XmlComment* xmlComment() 00754 { return 0; } 00755 00760 virtual XmlCData* xmlCData() 00761 { return 0; } 00762 00767 virtual XmlText* xmlText() 00768 { return 0; } 00769 00774 virtual XmlDeclaration* xmlDeclaration() 00775 { return 0; } 00776 00781 virtual XmlDoctype* xmlDoctype() 00782 { return 0; } 00783 }; 00784 00785 00790 class YXML_API XmlDeclaration : public XmlChild 00791 { 00792 YCLASS(XmlDeclaration,XmlChild) 00793 public: 00799 XmlDeclaration(const char* version = "1.0", const char* enc = "utf-8"); 00800 00805 XmlDeclaration(const NamedList& decl); 00806 00811 XmlDeclaration(const XmlDeclaration& orig); 00812 00816 ~XmlDeclaration(); 00817 00822 inline const NamedList& getDec() const 00823 { return m_declaration; } 00824 00830 virtual XmlDeclaration* xmlDeclaration() 00831 { return this; } 00832 00838 void toString(String& dump, bool escape = true) const; 00839 00840 private: 00841 NamedList m_declaration; // The declaration 00842 }; 00843 00848 class YXML_API XmlFragment : public XmlParent 00849 { 00850 public: 00851 00855 XmlFragment(); 00856 00861 XmlFragment(const XmlFragment& orig); 00862 00866 virtual ~XmlFragment(); 00867 00872 virtual XmlFragment* fragment() 00873 { return this; } 00874 00879 virtual const ObjList& getChildren() const 00880 { return m_list; } 00881 00887 virtual XmlSaxParser::Error addChild(XmlChild* child); 00888 00892 virtual void reset(); 00893 00898 inline XmlChild* pop() 00899 { return static_cast<XmlChild*>(m_list.remove(false)); } 00900 00907 virtual XmlChild* removeChild(XmlChild* child, bool delObj = true); 00908 00912 virtual void clearChildren() 00913 { m_list.clear(); } 00914 00927 void toString(String& dump, bool escape = true, const String& indent = String::empty(), 00928 const String& origIndent = String::empty(), bool completeOnly = true, 00929 const String* auth = 0, const XmlElement* parent = 0) const; 00930 00941 static XmlElement* findElement(ObjList* list, const String* name, const String* ns, 00942 bool noPrefix = true); 00943 00944 private: 00945 ObjList m_list; // The children list 00946 }; 00947 00952 class YXML_API XmlDocument : public XmlParent 00953 { 00954 public: 00955 00959 XmlDocument(); 00960 00964 virtual ~XmlDocument(); 00965 00970 virtual XmlDocument* document() 00971 { return this; } 00972 00982 virtual XmlSaxParser::Error addChild(XmlChild* child); 00983 00988 XmlDeclaration* declaration() const; 00989 00995 XmlElement* root(bool completed = false) const; 00996 01000 virtual void reset(); 01001 01008 virtual XmlChild* removeChild(XmlChild* child, bool delObj = true) 01009 { return m_beforeRoot.removeChild(child,delObj); } 01010 01017 virtual XmlSaxParser::Error read(Stream& in, int* error = 0); 01018 01031 virtual int write(Stream& out, bool escape = true, 01032 const String& indent = String::empty(), const String& origIndent = String::empty(), 01033 bool completeOnly = true) const; 01034 01042 XmlSaxParser::Error loadFile(const char* file, int* error = 0); 01043 01053 int saveFile(const char* file = 0, bool escape = true, 01054 const String& indent = String::empty(), bool completeOnly = true) const; 01055 01063 void toString(String& dump, bool escape = true, const String& indent = String::empty(), 01064 const String& origIndent = String::empty()) const; 01065 01066 private: 01067 XmlElement* m_root; // The root element 01068 XmlFragment m_beforeRoot; // XML children before root (declaration ...) 01069 String m_file; // The file name used on load 01070 }; 01071 01072 01078 class YXML_API XmlElement : public XmlChild, public XmlParent 01079 { 01080 YCLASS(XmlElement,XmlChild) 01081 public: 01088 XmlElement(const NamedList& element, bool empty, XmlParent* parent = 0); 01089 01095 XmlElement(const char* name, bool complete = true); 01096 01101 XmlElement(const XmlElement& orig); 01102 01106 virtual ~XmlElement(); 01107 01112 inline const char* tag() const 01113 { return m_element; } 01114 01119 inline bool isDefaultNs() const 01120 { return m_prefixed == 0; } 01121 01126 inline const String& unprefixedTag() const 01127 { return m_prefixed ? m_prefixed->name() : static_cast<const String&>(m_element); } 01128 01133 inline const String& getTag() const 01134 { return m_prefixed ? m_prefixed->name() : static_cast<const String&>(m_element); } 01135 01142 bool getTag(const String*& tag, const String*& ns) const; 01143 01148 virtual XmlElement* xmlElement() 01149 { return this; } 01150 01155 virtual XmlElement* element() 01156 { return this; } 01157 01162 virtual XmlSaxParser::Error addChild(XmlChild* child); 01163 01170 virtual XmlChild* removeChild(XmlChild* child, bool delObj = true); 01171 01175 virtual void setCompleted() 01176 { m_complete = true; } 01177 01181 inline bool completed() const 01182 { return m_complete; } 01183 01187 inline bool empty() const 01188 { return m_empty; } 01189 01194 inline XmlElement* parent() const 01195 { return m_parent ? m_parent->element() : 0; } 01196 01200 virtual XmlParent* getParent() 01201 { return m_parent; } 01202 01207 virtual void setParent(XmlParent* parent); 01208 01212 virtual const String& getName() const 01213 { return m_element; } 01214 01218 virtual const NamedList& getElement() const 01219 { return m_element; } 01220 01225 inline const ObjList& getChildren() const 01226 { return m_children.getChildren(); } 01227 01231 inline void clearChildren() 01232 { return m_children.clearChildren(); } 01233 01238 inline const NamedList* inheritedNs() const 01239 { return m_inheritedNs; } 01240 01246 void setInheritedNs(const XmlElement* xml = 0, bool inherit = true); 01247 01252 void addInheritedNs(const NamedList& list); 01253 01258 inline XmlElement* pop() { 01259 XmlElement* x = findFirstChild(); 01260 if (!(x && x->completed())) 01261 return 0; 01262 m_children.removeChild(x,false); 01263 return x; 01264 } 01265 01270 virtual const String& toString() const 01271 { return m_element; } 01272 01284 void toString(String& dump, bool escape = true, const String& indent = String::empty(), 01285 const String& origIndent = String::empty(), bool completeOnly = true, 01286 const String* auth = 0) const; 01287 01297 inline XmlElement* findFirstChild(const String* name = 0, const String* ns = 0, 01298 bool noPrefix = true) const 01299 { return XmlFragment::findElement(getChildren().skipNull(),name,ns,noPrefix); } 01300 01311 inline XmlElement* findNextChild(XmlElement* prev = 0, const String* name = 0, 01312 const String* ns = 0, bool noPrefix = true) const { 01313 if (!prev) 01314 return findFirstChild(name,ns,noPrefix); 01315 ObjList* start = getChildren().find(prev); 01316 return start ? XmlFragment::findElement(start->skipNext(),name,ns,noPrefix) : 0; 01317 } 01318 01322 const String& getText(); 01323 01328 void addText(const char* text); 01329 01334 inline const NamedList& attributes() const 01335 { return m_element; } 01336 01343 unsigned int copyAttributes(NamedList& list, const String& prefix) const; 01344 01350 inline void setAttribute(const String& name, const char* value) 01351 { m_element.setParam(name,value); } 01352 01358 inline void setAttributeValid(const String& name, const char* value) { 01359 if (!TelEngine::null(value)) 01360 m_element.setParam(name,value); 01361 else 01362 removeAttribute(name); 01363 } 01364 01370 inline const char* attribute(const String& name) const 01371 { return m_element.getValue(name); } 01372 01378 inline String* getAttribute(const String& name) const 01379 { return m_element.getParam(name); } 01380 01387 inline bool hasAttribute(const String& name, const String& value) const { 01388 String* a = getAttribute(name); 01389 return a && *a == value; 01390 } 01391 01396 inline void removeAttribute(const String& name) 01397 { m_element.clearParam(name); } 01398 01403 inline String* xmlns() const { 01404 if (!m_prefixed) 01405 return xmlnsAttribute(s_ns); 01406 return xmlnsAttribute(s_nsPrefix + *m_prefixed); 01407 } 01408 01413 String* xmlnsAttribute(const String& name) const; 01414 01420 inline bool hasXmlns(const String& ns) const { 01421 const String* x = xmlns(); 01422 return x && *x == ns; 01423 } 01424 01433 bool setXmlns(const String& name = String::empty(), bool addAttr = false, 01434 const String& value = String::empty()); 01435 01442 static inline bool isXmlns(const String& str) 01443 { return str == s_ns || str.startsWith(s_nsPrefix); } 01444 01461 static XmlElement* param2xml(NamedString* param, const String& tag, 01462 bool copyXml = false); 01463 01473 static NamedString* xml2param(XmlElement* xml, const String* tag, 01474 bool copyXml = false); 01475 01486 static void xml2param(NamedList& list, XmlElement* parent, const String* tag, 01487 bool copyXml = false); 01488 01492 static const String s_ns; 01493 01497 static const String s_nsPrefix; 01498 01499 private: 01500 // Set prefixed data (tag and prefix) 01501 inline void setPrefixed() { 01502 TelEngine::destruct(m_prefixed); 01503 int pos = m_element.find(":"); 01504 if (pos != -1) 01505 m_prefixed = new NamedString(m_element.substr(pos + 1),m_element.substr(0,pos)); 01506 } 01507 01508 XmlFragment m_children; // Children of this element 01509 NamedList m_element; // The element 01510 NamedString* m_prefixed; // Splitted prefixed tag (the value is the namespace prefix) 01511 XmlParent* m_parent; // The XmlElement who holds this element 01512 NamedList* m_inheritedNs; // Inherited namespaces (if parent is 0) 01513 bool m_empty; // True if this element does not have any children 01514 bool m_complete; // True if the end element tag war reported 01515 }; 01516 01521 class YXML_API XmlComment : public XmlChild 01522 { 01523 YCLASS(XmlComment,XmlChild) 01524 public: 01529 XmlComment(const String& comm); 01530 01535 XmlComment(const XmlComment& orig); 01536 01540 virtual ~XmlComment(); 01541 01546 inline const String& getComment() const 01547 { return m_comment; } 01548 01554 void toString(String& dump, const String& indent = String::empty()) const; 01555 01560 virtual XmlComment* xmlComment() 01561 { return this; } 01562 01563 private: 01564 String m_comment; // The comment 01565 }; 01566 01571 class YXML_API XmlCData : public XmlChild 01572 { 01573 YCLASS(XmlCData,XmlChild) 01574 public: 01575 01580 XmlCData(const String& data); 01581 01586 XmlCData(const XmlCData& orig); 01587 01591 virtual ~XmlCData(); 01592 01597 inline const String& getCData() const 01598 { return m_data;} 01599 01605 void toString(String& dump, const String& indent = String::empty()) const; 01606 01611 virtual XmlCData* xmlCData() 01612 { return this; } 01613 01614 private: 01615 String m_data; // The data 01616 }; 01617 01622 class YXML_API XmlText : public XmlChild 01623 { 01624 YCLASS(XmlText,XmlChild) 01625 public: 01630 XmlText(const String& text); 01631 01636 XmlText(const XmlText& orig); 01637 01641 virtual ~XmlText(); 01642 01646 inline const String& getText() const 01647 { return m_text; } 01648 01659 void toString(String& dump, bool escape = true, const String& indent = String::empty(), 01660 const String* auth = 0, const XmlElement* parent = 0) const; 01661 01666 virtual XmlText* xmlText() 01667 { return this; } 01668 01669 private: 01670 String m_text; // The text 01671 }; 01672 01673 class YXML_API XmlDoctype : public XmlChild 01674 { 01675 YCLASS(XmlDoctype,XmlChild) 01676 public: 01681 XmlDoctype(const String& doctype); 01682 01687 XmlDoctype(const XmlDoctype& orig); 01688 01692 virtual ~XmlDoctype(); 01693 01698 inline const String& getDoctype() const 01699 { return m_doctype; } 01700 01705 virtual XmlDoctype* xmlDoctype() 01706 { return this; } 01707 01713 void toString(String& dump, const String& indent = String::empty()) const; 01714 01715 private: 01716 String m_doctype; // The document type 01717 }; 01718 01719 }; // namespace TelEngine 01720 01721 #endif /* __YATEXML_H */ 01722 01723 /* vi: set ts=8 sw=4 sts=4 noet: */