/* * yatexml.h * This file is part of the YATE Project http://YATE.null.ro * * XML Parser and support classes * * Yet Another Telephony Engine - a fully featured software PBX and IVR * Copyright (C) 2004-2006 Null Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __YATEXML_H #define __YATEXML_H #include #ifdef _WINDOWS #ifdef LIBYXML_EXPORTS #define YXML_API __declspec(dllexport) #else #ifndef LIBYXML_STATIC #define YXML_API __declspec(dllimport) #endif #endif #endif /* _WINDOWS */ #ifndef YXML_API #define YXML_API #endif /** * Holds all Telephony Engine related classes. */ namespace TelEngine { class XmlSaxParser; class XmlDomParser; class XmlDeclaration; class XmlFragment; class XmlChild; class XmlParent; class XmlDocument; class XmlElement; class XmlComment; class XmlCData; class XmlText; class XmlDoctype; struct YXML_API XmlEscape { /** * Value to match */ const char* value; /** * Character replacement for value */ char replace; }; /** * A Serial Access Parser (SAX) for arbitrary XML data * @short Serial Access XML Parser */ class YXML_API XmlSaxParser : public DebugEnabler { public: enum Error { NoError = 0, NotWellFormed, Unknown, IOError, ElementParse, ReadElementName, InvalidElementName, ReadingAttributes, CommentParse, DeclarationParse, DefinitionParse, CDataParse, ReadingEndTag, Incomplete, InvalidEncoding, UnsupportedEncoding, UnsupportedVersion, }; enum Type { None = 0, Text = 1, CData = 2, Element = 3, Doctype = 4, Comment = 5, Declaration = 6, Instruction = 7, EndTag = 8, Special = 9 }; /** * Destructor */ virtual ~XmlSaxParser(); /** * Get the number of bytes successfully parsed * @return The number of bytes successfully parsed */ inline unsigned int offset() const { return m_offset; } /** * Get the row where the parser has found an error * @return The row number */ inline unsigned int row() const { return m_row; } /** * Get the column where the parser has found an error * @return The column number */ inline unsigned int column() const { return m_column; } /** * Retrieve the parser's buffer * @return The parser's buffer */ inline const String& buffer() const { return m_buf; } /** * Parse a given string * @param data The data to parse * @return True if all data was successfully parsed */ bool parse(const char* data); /** * Get the error code found while parsing * @return Error code */ inline Error error() { return m_error; } /** * Set the error code and destroys a child if error code is not NoError * @param error The error found * @param child Child to destroy * @return False on error */ bool setError(Error error, XmlChild* child = 0); /** * Retrieve the error string associated with current error status * @param defVal Value to return if not found * @return The error string */ inline const char* getError(const char* defVal = "Xml error") { return getError(m_error,defVal); } /** * @return The last xml type that we were parsing, but we have not finished */ inline Type unparsed() { return m_unparsed; } /** * Set the last xml type that we were parsing, but we have not finished * @param id The xml type that we haven't finish to parse */ inline void setUnparsed(Type id) { m_unparsed = id;} /** * Reset error flag */ virtual void reset(); /** * @return The internal buffer */ const String& getBuffer() const { return m_buf; } /** * Retrieve the error string associated with a given error code * @param code Code of the error to look up * @param defVal Value to return if not found * @return The error string */ static inline const char* getError(int code, const char* defVal = "Xml error") { return lookup(code,s_errorString,defVal); } /** * XmlEscape the given text * @param buf Destination buffer * @param text The text to escape */ static void escape(String& buf, const String& text); /** * Errors dictionary */ static const TokenDict s_errorString[]; /** * Escaped strings dictionary */ static const XmlEscape s_escape[]; protected: /** * Constructor * @param name Debug name */ XmlSaxParser(const char* name = "XmlSaxParser"); /** * Parse an instruction form the main buffer. * Extracts the parsed string from buffer if returns true * @return True if the instruction was parsed successfully */ bool parseInstruction(); /** * Parse a CData section form the main buffer. * Extracts the parsed string from buffer if returns true * @return True if the CData section was parsed successfully */ bool parseCData(); /** * Parse a comment form the main buffer. * Extracts the parsed string from buffer if returns true * @return True if the comment was parsed successfully */ bool parseComment(); /** * Parse an element form the main buffer. * Extracts the parsed string from buffer if returns true * @return True if the element was parsed successfully */ bool parseElement(); /** * Parse a declaration form the main buffer. * Extracts the parsed string from buffer if returns true * @return True if the declaration was parsed successfully */ bool parseDeclaration(); /** * Helper method to classify the Xml objects starting with "'; } /** * Reset the error */ inline void resetError() { m_error = NoError; } /** * Reset parsed value and parameters */ inline void resetParsed() { m_parsed.clear(); m_parsed.clearParams(); } /** * Extract the name of an element or instruction * @return The extracted string or 0 */ String* extractName(bool& empty); /** * Extract an attribute * @return The attribute value or 0 */ NamedString* getAttribute(); /** * Verify if the given character is in the range allowed * to be first character from a xml tag * @param ch The character to check * @return True if the character is in range */ bool checkFirstNameCharacter(unsigned char ch); /** * Check if the given character is in the range allowed for an xml char * @param c The character to check * @return True if the character is in range */ bool checkDataChar(unsigned char c); /** * Verify if the given character is in the range allowed for a xml name * @param ch The character to check * @return True if the character is in range */ bool checkNameCharacter(unsigned char ch); /** * Callback method. Is called when a comment was successfully parsed. * Default implementation does nothing * @param text The comment content */ virtual void gotComment(const String& text) { } /** * Callback method. Is called when an instruction was successfully parsed. * Default implementation does nothing * @param instr The instruction content */ virtual void gotProcessing(const NamedString& instr) { } /** * Callback method. Is called when a declaration was successfully parsed. * Default implementation does nothing * @param decl The declaration content */ virtual void gotDeclaration(const NamedList& decl) { } /** * Callback method. Is called when a text was successfully parsed. * Default implementation does nothing * @param text The text content */ virtual void gotText(const String& text) { } /** * Callback method. Is called when a CData section was successfully parsed. * Default implementation does nothing * @param data The CData content */ virtual void gotCdata(const String& data) { } /** * Callback method. Is called when an element was successfully parsed. * Default implementation does nothing * @param element The element content * @param empty True if the element does not have attributes */ virtual void gotElement(const NamedList& element, bool empty) { } /** * Callback method. Is called when a end tag was successfully parsed. * Default implementation does nothing * @param name The end tag name */ virtual void endElement(const String& name) { } /** * Callback method. Is called when a doctype was successfully parsed. * Default implementation does nothing * @param doc The doctype content */ virtual void gotDoctype(const String& doc) { } /** * Callback method. Is called to check if we have an incomplete element. * Default implementation returns always true * @return True */ virtual bool completed() { return true; } /** * Calls gotElement() and eset parsed on success * @param list The list element and its attributes * @param empty True if the element does not have attributes * @return True if there is no error */ bool processElement(NamedList& list, bool empty); /** * The offset where the parser was stop */ unsigned int m_offset; /** * The row where the parser was stop */ unsigned int m_row; /** * The column where the parser was stop */ unsigned int m_column; /** * The error code found while parsing data */ Error m_error; /** * The main buffer */ String m_buf; /** * The parser data holder. * Keeps the parsed data when an incomplete xml object is found */ NamedList m_parsed; /** * The last parsed xml object code */ Type m_unparsed; }; /** * Xml Parent for a Xml child * @short Xml Parent */ class YXML_API XmlParent { public: /** * Constructor */ XmlParent() { } /** * Destructor */ virtual ~XmlParent() { } /** * Get an XmlDocument object from this XmlParent. * Default implementation return 0 * @return 0 */ virtual XmlDocument* document() { return 0; } /** * Get an XmlFragment object from this XmlParent. * Default implementation return 0 * @return 0 */ virtual XmlFragment* fragment() { return 0; } /** * Get an XmlElement object from this XmlParent. * Default implementation return 0 * @return 0 */ virtual XmlElement* element() { return 0; } /** * Append a new child to this XmlParent * @param child The child to append * @return XmlNoError if the child was successfully added */ virtual XmlSaxParser::Error addChild(XmlChild* child) = 0; /** * Remove a child * @param child The child to remove * @param delObj True to delete the object * @return XmlChild pointer if found and not deleted */ virtual XmlChild* removeChild(XmlChild* child, bool delObj = true) = 0; /** * Reset this xml parent. * Default implementation does nothing */ virtual void reset() { } /** * Obtain this xml parent children. * Default implementation returns an empty list * @return The list of children */ virtual const ObjList& getChildren() const { return ObjList::empty(); } /** * Clear this xml parent children. * Default implementation does nothing */ virtual void clearChildren() { } }; /** * A Document Object Model (DOM) parser for XML documents and fragments * @short Document Object Model XML Parser */ class YXML_API XmlDomParser : public XmlSaxParser { friend class XmlChild; public: /** * XmlDomParser constructor * @param name Debug name * @param fragment True if this parser needs to parse a piece of a xml document */ XmlDomParser(const char* name = "XmlDomParser", bool fragment = false); /** * XmlDomParser constructor * @param fragment The fragment who should keep the parsed data */ XmlDomParser(XmlParent* fragment); /** * Destructor */ virtual ~XmlDomParser(); /** * Obtain an XmlDocument from the parsed data * @return The XmlDocument or 0 */ XmlDocument* document() { return m_data->document(); } /** * Obtain an XmlFragment from the parsed data * @return The XmlFragment or 0 */ XmlFragment* fragment() { return m_data->fragment(); } /** * Reset parser */ virtual void reset(); /** * Check if the current element is the given one * @param el The element to compare with * @return True if they are equal */ inline bool isCurrent(const XmlElement* el) const { return el == m_current; } protected: /** * Append a xml comment in the xml tree * @param text The comment content */ virtual void gotComment(const String& text); /** * Append a xml instruction in the xml tree * @param instr The instruction content */ virtual void gotProcessing(const NamedString& instr); /** * Append a xml declaration in the xml tree * @param decl The declaration content */ virtual void gotDeclaration(const NamedList& decl); /** * Append a xml text in the xml tree * @param text The text content */ virtual void gotText(const String& text); /** * Append a xml CData in the xml tree * @param data The CData content */ virtual void gotCdata(const String& data); /** * Append a xml element in the xml tree * @param element The element content * @param empty True if the element does not have attributes */ virtual void gotElement(const NamedList& element, bool empty); /** * Complete current element * @param name The end tag name */ virtual void endElement(const String& name); /** * Append a xml doctype in the xml tree * @param doc The doctype content */ virtual void gotDoctype(const String& doc); /** * Callback method. Is called to check if we have an incomplete element * @return True if current element is not 0 */ virtual bool completed() { return m_current == 0; } private: XmlElement* m_current; // The current xml element XmlParent* m_data; // Main xml fragment }; /** * Xml Child for Xml document * @short Xml Child */ class YXML_API XmlChild : public GenObject { YCLASS(XmlChild,GenObject) friend class XmlDomParser; public: /** * Constructor */ XmlChild(); /** * Set this child's parent * @param parent Parent of this child */ virtual void setParent(XmlParent* parent) { } /** * Get a Xml element * @return 0 */ virtual XmlElement* xmlElement() { return 0; } /** * Get a Xml comment * @return 0 */ virtual XmlComment* xmlComment() { return 0; } /** * Get a Xml CData * @return 0 */ virtual XmlCData* xmlCData() { return 0; } /** * Get a Xml text * @return 0 */ virtual XmlText* xmlText() { return 0; } /** * Get a Xml declaration * @return 0 */ virtual XmlDeclaration* xmlDeclaration() { return 0; } /** * Get a Xml doctype * @return 0 */ virtual XmlDoctype* xmlDoctype() { return 0; } }; /** * Xml Declaration for Xml document * @short Xml Declaration */ class YXML_API XmlDeclaration : public XmlChild { YCLASS(XmlDeclaration,XmlChild) public: /** * Constructor * @param version XML version attribute * @param enc Encoding attribute */ XmlDeclaration(const char* version = "1.0", const char* enc = "utf-8"); /** * Constructor * @param decl Declaration attributes */ XmlDeclaration(const NamedList& decl); /** * Copy constructor * @param orig Original XmlDeclaration */ XmlDeclaration(const XmlDeclaration& orig); /** * Destructor */ ~XmlDeclaration(); /** * Obtain the tag name and attributes list * @return The declaration */ inline const NamedList& getDec() const { return m_declaration; } /** * Get the Xml declaration * @return This object * Reimplemented from XmlChild */ virtual XmlDeclaration* xmlDeclaration() { return this; } /** * Build a String from this XmlDeclaration * @param dump The string where to append representation * @param escape True if the attributes values need to be escaped */ void toString(String& dump, bool escape = true) const; private: NamedList m_declaration; // The declaration }; /** * Xml Fragment a fragment from a Xml document * @short Xml Fragment */ class YXML_API XmlFragment : public XmlParent { public: /** * Constructor */ XmlFragment(); /** * Copy constructor * @param orig Original XmlFragment */ XmlFragment(const XmlFragment& orig); /** * Destructor */ virtual ~XmlFragment(); /** * Get an Xml Fragment * @return This */ virtual XmlFragment* fragment() { return this; } /** * Get the list of children * @return The children list */ virtual const ObjList& getChildren() const { return m_list; } /** * Append a new xml child to this fragment * @param child the child to append * @return An error code if an error was detected */ virtual XmlSaxParser::Error addChild(XmlChild* child); /** * Reset this Xml Fragment */ virtual void reset(); /** * Remove the first child from list and returns it * @return XmlChild pointer or 0 */ inline XmlChild* pop() { return static_cast(m_list.remove(false)); } /** * Remove a child. Reset the parent of not deleted xml element * @param child The child to remove * @param delObj True to delete the object * @return XmlChild pointer if found and not deleted */ virtual XmlChild* removeChild(XmlChild* child, bool delObj = true); /** * Clear the list of children */ virtual void clearChildren() { m_list.clear(); } /** * Build a String from this XmlFragment * @param dump The string where to append representation * @param escape True if the attributes values need to be escaped * @param indent Spaces for output * @param origIndent Original indent * @param completeOnly True to build only if complete * @param auth Optional list of tag and attribute names to be replaced with '***'. This * parameter can be used when the result will be printed to output to avoid printing * authentication data to output. The array must end with an empty string * @param parent Optional parent element whose tag will be searched in the auth list */ void toString(String& dump, bool escape = true, const String& indent = String::empty(), const String& origIndent = String::empty(), bool completeOnly = true, const String* auth = 0, const XmlElement* parent = 0) const; /** * Find a completed xml element in a list * @param list The list to search for the element * @param name Optional element tag to match * @param ns Optional element namespace to match * @return XmlElement pointer or 0 if not found */ static XmlElement* findElement(ObjList* list, const String* name, const String* ns); private: ObjList m_list; // The children list }; /** * Xml Document * @short Xml Document */ class YXML_API XmlDocument : public XmlParent { public: /** * The Constructor */ XmlDocument(); /** * Destructor */ virtual ~XmlDocument(); /** * Get an Xml Document * @return This */ virtual XmlDocument* document() { return this; } /** * Append a new child to this document. * Set the root to an XML element if not already set. If we already have a completed root * the element will be added to the root, otherwise an error will be returned. * If we don't have a root non xml elements (other then text) will be added the list * of elements before root * @param child The child to append * @return An error code if an error was detected */ virtual XmlSaxParser::Error addChild(XmlChild* child); /** * Retrieve the document declaration * @return XmlDeclaration pointer or 0 if not found */ XmlDeclaration* declaration() const; /** * Retrieve the root element * @param completed True to retrieve the root element if is not completed * @return Root pointer or 0 if not found or is not completed */ XmlElement* root(bool completed = false) const; /** * Reset this Xml Document */ virtual void reset(); /** * Remove a child * @param child The child to remove * @param delObj True to delete the object * @return XmlChild pointer if found and not deleted */ virtual XmlChild* removeChild(XmlChild* child, bool delObj = true) { return m_beforeRoot.removeChild(child,delObj); } /** * Load this document from data stream and parse it. * @param in The input stream * @param error Optional pointer to data to be filled with error if IOError is returned * @return Parser error (NoError on success) */ virtual XmlSaxParser::Error read(Stream& in, int* error = 0); /** * Write this document to a data stream. * A indent + n * origIndent will be added before each xml child, * where n is the imbrication level, starting with 0. * A indent + (n + 1) * origIndent will be added before each attribute * @param out The output stream * @param escape True if the attributes values need to be escaped * @param indent Line indent * @param origIndent Original indent * @param completeOnly True to build only if complete * @return Written bytes, negative on error */ virtual int write(Stream& out, bool escape = true, const String& indent = String::empty(), const String& origIndent = String::empty(), bool completeOnly = true) const; /** * Load a file an parse it * Reset the document * @param file The file to load * @param error Pointer to data to be filled with file error if IOError is returned * @return Parser error (NoError on success) */ XmlSaxParser::Error loadFile(const char* file, int* error = 0); /** * Save this xml document in the specified file. Create a new fle if not found. * Truncate an existing one * @param file The file to save or will be used the file used on load * @param escape True if the attributes values need to be escaped * @param indent Spaces for output * @param completeOnly True to build only if complete * @return 0 on success, error code on failure */ int saveFile(const char* file = 0, bool escape = true, const String& indent = String::empty(), bool completeOnly = true) const; /** * Build a String from this XmlDocument * @param dump The string where to append representation * @param escape True if the attributes values need to be escaped * @param indent Spaces for output * @param origIndent Original indent */ void toString(String& dump, bool escape = true, const String& indent = String::empty(), const String& origIndent = String::empty()) const; private: XmlElement* m_root; // The root element XmlFragment m_beforeRoot; // XML children before root (declaration ...) String m_file; // The file name used on load }; /** * Xml Element from a Xml document * @short Xml Element */ class YXML_API XmlElement : public XmlChild, public XmlParent { YCLASS(XmlElement,XmlChild) public: /** * Constructor * @param element The NamedList name represent the element name and the param the attributes * @param empty False if has children * @param parent The parent of this element */ XmlElement(const NamedList& element, bool empty, XmlParent* parent = 0); /** * Constructor. Creates a new complete and empty element * @param name The name of the element * @param complete False to build an incomplete element */ XmlElement(const char* name, bool complete = true); /** * Copy constructor * @param orig Original XmlElement */ XmlElement(const XmlElement& orig); /** * Destructor */ virtual ~XmlElement(); /** * Retrieve the element's tag * @return The element's tag */ inline const char* tag() const { return m_element; } /** * Check if this element must be processed in the default namespace (its tag is not prefixed) * @return True if this element must be processed in the default namespace */ inline bool isDefaultNs() const { return m_prefixed == 0; } /** * Retrieve the element's tag unprefixed (namespace prefix removed) * @return The element's tag unprefixed */ inline const String& unprefixedTag() const { return m_prefixed ? m_prefixed->name() : static_cast(m_element); } /** * Retrieve the element's tag (without prefix) * @return Element tag */ inline const String& getTag() const { return m_prefixed ? m_prefixed->name() : static_cast(m_element); } /** * Retrieve the element's tag (without prefix) and namespace * @param tag Pointer to element tag * @param ns Pointer to element's namespace (may be 0 for unprefixed tags) * @return True if a namespace was found for the element tag or the tag is not prefixed */ bool getTag(const String*& tag, const String*& ns) const; /** * Get an XmlElement from this XmlChild * @return This object */ virtual XmlElement* xmlElement() { return this; } /** * Get an XmlElement from this XmlParent * @return This object */ virtual XmlElement* element() { return this; } /** * Append a new child of this element * @param child The child to append */ virtual XmlSaxParser::Error addChild(XmlChild* child); /** * Remove a child * @param child The child to remove * @param delObj True to delete the object * @return XmlChild pointer if found and not deleted */ virtual XmlChild* removeChild(XmlChild* child, bool delObj = true); /** * Notification for this element that is complete */ virtual void setCompleted() { m_complete = true; } /** * @return True if this element is completed */ inline bool completed() const { return m_complete; } /** * @return True if this element is empty */ inline bool empty() const { return m_empty; } /** * Retrieve an XmlElement parent of this one * @return XmlElement pointer or 0 */ inline XmlElement* parent() const { return m_parent ? m_parent->element() : 0; } /** * @return The parent of this element */ virtual XmlParent* getParent() { return m_parent; } /** * Set this element's parent. Update inherited namespaces * @return The parent of this element */ virtual void setParent(XmlParent* parent); /** * @return The name of this element */ virtual const String& getName() const { return m_element; } /** * @return The held element */ virtual const NamedList& getElement() const { return m_element; } /** * Helper method to obtain the children list * @return The children list */ inline const ObjList& getChildren() const { return m_children.getChildren(); } /** * Helper method to clear the children list */ inline void clearChildren() { return m_children.clearChildren(); } /** * Retrieve the list of inherited namespaces * @return The list of inherited namespaces (or 0) */ inline const NamedList* inheritedNs() const { return m_inheritedNs; } /** * Set inherited namespaces from a given element. Reset them anyway * @param xml The source element used to set inherited namespaces * @param inherit Copy element's inherited namespaces if it doesn't have a parent */ void setInheritedNs(const XmlElement* xml = 0, bool inherit = true); /** * Add inherited namespaces from a list * @param list The list of namespaces */ void addInheritedNs(const NamedList& list); /** * Extract the first child element * @return XmlElement pointer or 0 */ inline XmlElement* pop() { XmlElement* x = findFirstChild(); if (!(x && x->completed())) return 0; m_children.removeChild(x,false); return x; } /** * Retrieve the element tag * @return The element tag */ virtual const String& toString() const { return m_element; } /** * Build (append to) a String from this XmlElement * @param dump The destination string * @param escape True if the attributes values need to be escaped * @param indent Spaces for output * @param origIndent Original indent * @param completeOnly True to build only if complete * @param auth Optional list of tag and attribute names to be replaced with '***'. This * parameter can be used when the result will be printed to output to avoid printing * authentication data to output. The array must end with an empty string */ void toString(String& dump, bool escape = true, const String& indent = String::empty(), const String& origIndent = String::empty(), bool completeOnly = true, const String* auth = 0) const; /** * Find the first child of this XmlElement * @param name Optional name of the child * @param ns Optional child namespace * @return The first child element meeting the requested conditions */ inline XmlElement* findFirstChild(const String* name = 0, const String* ns = 0) const { return XmlFragment::findElement(getChildren().skipNull(),name,ns); } /** * Finds next child of this XmlElement * @param prev Previous child * @param name Optional name of the child * @param ns Optional child namespace * @return The next found child if prev exists else the first */ inline XmlElement* findNextChild(XmlElement* prev = 0, const String* name = 0, const String* ns = 0) const { if (!prev) return findFirstChild(name,ns); ObjList* start = getChildren().find(prev); return start ? XmlFragment::findElement(start->skipNext(),name,ns) : 0; } /** * @return The first XmlText found in this XmlElement children */ const String& getText(); /** * Add a text child * @param text Non empty text to add */ void addText(const char* text); /** * Retrieve the list of attributes * @return Element attributes */ inline const NamedList& attributes() const { return m_element; } /** * Copy element attributes to a list of parameters * @list Destination list * @prefix Prefix to be added to each attribute name * @return The number of attributes added to the destination list */ unsigned int copyAttributes(NamedList& list, const String& prefix) const; /** * Add or replace an attribute * @param name Attribute name * @param value Attribute value */ inline void setAttribute(const String& name, const char* value) { m_element.setParam(name,value); } /** * Add or replace an attribute. Clears it if value is empty * @param name Attribute name * @param value Attribute value */ inline void setAttributeValid(const String& name, const char* value) { if (!TelEngine::null(value)) m_element.setParam(name,value); else removeAttribute(name); } /** * Obtain an attribute value for the given name * @param name The name of the attribute * @return Attribute value */ inline const char* attribute(const String& name) const { return m_element.getValue(name); } /** * Obtain an attribute value for the given name * @param name The name of the attribute * @return String pointer or 0 if not found */ inline String* getAttribute(const String& name) const { return m_element.getParam(name); } /** * Check if the element has an attribute with a requested value * @param name The name of the attribute * @param value The value to check * @return True if the element has an attribute with the requested value */ inline bool hasAttribute(const String& name, const String& value) const { String* a = getAttribute(name); return a && *a == value; } /** * Remove an attribute * @param name Attribute name */ inline void removeAttribute(const String& name) { m_element.clearParam(name); } /** * Retrieve the element's namespace * @return Element's namespace or 0 if not found */ inline String* xmlns() const { if (!m_prefixed) return xmlnsAttribute(s_ns); return xmlnsAttribute(s_nsPrefix + *m_prefixed); } /** * Retrieve a namespace attribute. Search in parent or inherited for it * @return String pointer or 0 if not found */ String* xmlnsAttribute(const String& name) const; /** * Verify if this element belongs to the given namespace * @param ns The namespace to compare with * @return True if this element belongs to the given namespace */ inline bool hasXmlns(const String& ns) const { const String* x = xmlns(); return x && *x == ns; } /** * Set the element's namespace * @param name The namespace name (element prefix). Can be the default * namespace attribute name (empty means the default one) * @param addAttr True to add a non empty, not repeating, namespace attribute to the list * @param value Namespace value (ignored if addAttr is false) * @return True on success, false if another namespace exists with the same value */ bool setXmlns(const String& name = String::empty(), bool addAttr = false, const String& value = String::empty()); /** * Check if a string represents a namespace attribute name * @param str The string to check * @return True if the given string is the default namespace attribute name or * a namespace attribute name prefix */ static inline bool isXmlns(const String& str) { return str == s_ns || str.startsWith(s_nsPrefix); } /** * Default namespace attribute name */ static const String s_ns; /** * Namespace attribute name perfix */ static const String s_nsPrefix; private: // Set prefixed data (tag and prefix) inline void setPrefixed() { TelEngine::destruct(m_prefixed); int pos = m_element.find(":"); if (pos != -1) m_prefixed = new NamedString(m_element.substr(pos + 1),m_element.substr(0,pos)); } XmlFragment m_children; // Children of this element NamedList m_element; // The element NamedString* m_prefixed; // Splitted prefixed tag (the value is the namespace prefix) XmlParent* m_parent; // The XmlElement who holds this element NamedList* m_inheritedNs; // Inherited namespaces (if parent is 0) bool m_empty; // True if this element does not have any children bool m_complete; // True if the end element tag war reported }; /** * A Xml Comment from Xml document * @short Xml Comment */ class YXML_API XmlComment : public XmlChild { YCLASS(XmlComment,XmlChild) public: /** * Constructor * @param comm The comment content */ XmlComment(const String& comm); /** * Copy constructor * @param orig Original XmlComment */ XmlComment(const XmlComment& orig); /** * Destructor */ virtual ~XmlComment(); /** * Get the text contained by this comment * @return The comment */ inline const String& getComment() const { return m_comment; } /** * Build a String from this XmlComment * @param dump The string where to append representation * @param indent Spaces for output */ void toString(String& dump, const String& indent = String::empty()) const; /** * Get the Xml comment * @return This object */ virtual XmlComment* xmlComment() { return this; } private: String m_comment; // The comment }; /** * A Xml CData from Xml document * @short Xml Declaration */ class YXML_API XmlCData : public XmlChild { YCLASS(XmlCData,XmlChild) public: /** * Constructor * @param data The CData content */ XmlCData(const String& data); /** * Copy constructor * @param orig Original XmlCData */ XmlCData(const XmlCData& orig); /** * Destructor */ virtual ~XmlCData(); /** * Get the CData content * @return The content of this xml object */ inline const String& getCData() const { return m_data;} /** * Build a String from this XmlCData * @param dump The string where to append representation * @param indent Spaces for output */ void toString(String& dump, const String& indent = String::empty()) const; /** * Get the Xml CData * @return This object */ virtual XmlCData* xmlCData() { return this; } private: String m_data; // The data }; /** * A Xml Declaration for Xml document * @short Xml Declaration */ class YXML_API XmlText : public XmlChild { YCLASS(XmlText,XmlChild) public: /** * Constructor * @param text The text */ XmlText(const String& text); /** * Copy constructor * @param orig Original XmlText */ XmlText(const XmlText& orig); /** * Destructor */ virtual ~XmlText(); /** * @return The text kept by this Xml Text */ inline const String& getText() const { return m_text; } /** * Build a String from this XmlText * @param dump The string where to append representation * @param escape True if the text need to be escaped * @param indent Spaces for output * @param auth Optional list of tag and attribute names to be replaced with '***'. This * parameter can be used when the result will be printed to output to avoid printing * authentication data to output. The array must end with an empty string * @param parent Optional parent element whose tag will be searched in the auth list */ void toString(String& dump, bool escape = true, const String& indent = String::empty(), const String* auth = 0, const XmlElement* parent = 0) const; /** * Get the Xml text * @return This object */ virtual XmlText* xmlText() { return this; } private: String m_text; // The text }; class YXML_API XmlDoctype : public XmlChild { YCLASS(XmlDoctype,XmlChild) public: /** * Constructor * @param doctype The doctype */ XmlDoctype(const String& doctype); /** * Copy constructor * @param orig Original XmlDoctype */ XmlDoctype(const XmlDoctype& orig); /** * Destructor */ virtual ~XmlDoctype(); /** * Get the doctype held by this Xml doctype * @return The content of this Xml doctype */ inline const String& getDoctype() const { return m_doctype; } /** * Get the Xml doctype * @return This object */ virtual XmlDoctype* xmlDoctype() { return this; } /** * Build a String from this XmlDoctype * @param dump The string where to append representation * @param indent Spaces for output */ void toString(String& dump, const String& indent = String::empty()) const; private: String m_doctype; // The document type }; }; // namespace TelEngine #endif /* __YATEXML_H */ /* vi: set ts=8 sw=4 sts=4 noet: */