Yate
yatexml.h
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: */