You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2197 lines
62 KiB
2197 lines
62 KiB
/**
|
|
* 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-2014 Null Team
|
|
*
|
|
* This software is distributed under multiple licenses;
|
|
* see the COPYING file in the main directory for licensing
|
|
* information for this specific distribution.
|
|
*
|
|
* This use of this software may be subject to additional restrictions.
|
|
* See the LEGAL file in the main directory for details.
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#ifndef __YATEXML_H
|
|
#define __YATEXML_H
|
|
|
|
#ifndef __cplusplus
|
|
#error C++ is required
|
|
#endif
|
|
|
|
#include <yateclass.h>
|
|
|
|
/**
|
|
* 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;
|
|
class XPath;
|
|
|
|
struct YATE_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 YATE_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);
|
|
|
|
/**
|
|
* Process incomplete text if the parser is completed.
|
|
* This method should be called to complete text after
|
|
* all data was pushed into the parser
|
|
* @return True if all data was successfully parsed
|
|
*/
|
|
bool completeText();
|
|
|
|
/**
|
|
* 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); }
|
|
|
|
/**
|
|
* Check if the given character is blank
|
|
* @param c The character to verify
|
|
* @return True if c is blank
|
|
*/
|
|
static inline bool blank(char c)
|
|
{ return (c <= 0x20) && ((c == 0x20) || (c == 0x09) || (c == 0x0d) || (c == 0x0a)); }
|
|
|
|
/**
|
|
* 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
|
|
*/
|
|
static inline bool checkFirstNameCharacter(unsigned char ch) {
|
|
return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')
|
|
|| (ch == ':') || (ch == '_')
|
|
|| (ch >= 0xc0 && ch <= 0xd6) || (ch >= 0xd8 && ch <= 0xf6) || (ch >= 0xf8);
|
|
}
|
|
|
|
/**
|
|
* 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
|
|
*/
|
|
static 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
|
|
*/
|
|
static inline bool checkNameCharacter(unsigned char ch) {
|
|
return checkFirstNameCharacter(ch) || ch == '-' || ch == '.' || (ch >= '0' && ch <= '9')
|
|
|| ch == 0xB7;
|
|
}
|
|
|
|
/**
|
|
* Check if a given string is a valid xml tag name
|
|
* @param buf The string to check
|
|
* @return True if the string is a valid xml tag name
|
|
*/
|
|
static bool validTag(const String& buf);
|
|
|
|
/**
|
|
* XmlEscape the given text
|
|
* @param buf Destination buffer
|
|
* @param text The text to escape
|
|
* @return Destination buffer reference
|
|
*/
|
|
static String& escape(String& buf, const String& text);
|
|
|
|
/**
|
|
* Unescape the given text.
|
|
* Handled: &lt; &gt; &apos; &quot; &amp;
|
|
* &\#DecimalNumber; &\#xHexNumber;
|
|
* @param text The requested text to unescape
|
|
* @param error Destination for error string
|
|
* @param found Optional flag to be set if unescape was found
|
|
* @return True on success, false otherwise
|
|
*/
|
|
static inline bool unEscape(String& text, String* error, bool* found = 0)
|
|
{ return unEscape(text,text.c_str(),text.length(),error,false,found); }
|
|
|
|
/**
|
|
* Unescape the given text.
|
|
* Handled: &lt; &gt; &apos; &quot; &amp;
|
|
* &\#DecimalNumber; &\#xHexNumber;
|
|
* @param text The requested text to unescape
|
|
* @param str Input buffer
|
|
* @param len Input buffer length
|
|
* @param inText Use destination text during unescape.
|
|
* If enabled the destination text may be incomplete on failure.
|
|
* The method will use a temporary buffer if disabled
|
|
* This parameter is ignored and handled as 'false' if 'str' points to destination string's buffer
|
|
* @param error Destination for error string
|
|
* @param found Optional flag to be set if unescape was found
|
|
* @return True on success, false otherwise
|
|
*/
|
|
static bool unEscape(String& text, const char* str, unsigned int len, String* error,
|
|
bool inText = false, bool* found = 0);
|
|
|
|
/**
|
|
* 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 "<!" sequence.
|
|
* Extracts the parsed string from buffer if returns true
|
|
* @return True if a corresponding xml object was found and parsed successfully
|
|
*/
|
|
bool parseSpecial();
|
|
|
|
/**
|
|
* Parse an endtag form the main buffer.
|
|
* Extracts the parsed string from buffer if returns true
|
|
* @return True if the endtag was parsed successfully
|
|
*/
|
|
bool parseEndTag();
|
|
|
|
/**
|
|
* Parse a doctype form the main buffer.
|
|
* Extracts the parsed string from buffer if returns true.
|
|
* Warning: This is a stub implementation
|
|
* @return True if the doctype was parsed successfully
|
|
*/
|
|
bool parseDoctype();
|
|
|
|
/**
|
|
* Parse an unfinished xml object.
|
|
* Extracts the parsed string from buffer if returns true
|
|
* @return True if the object was parsed successfully
|
|
*/
|
|
bool auxParse();
|
|
|
|
/**
|
|
* Unescape the given text.
|
|
* Handled: &lt; &gt; &apos; &quot; &amp;
|
|
* &\#DecimalNumber; &\#xHexNumber;
|
|
* @param text The requested text to unescape
|
|
*/
|
|
void unEscape(String& text);
|
|
|
|
/**
|
|
* Remove blank characters from the begining of the buffer
|
|
*/
|
|
void skipBlanks();
|
|
|
|
/**
|
|
* Check if a character is an angle bracket
|
|
* @param c The character to verify
|
|
* @return True if c is an angle bracket
|
|
*/
|
|
inline bool badCharacter(char c)
|
|
{ return c == '<' || c == '>'; }
|
|
|
|
/**
|
|
* 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();
|
|
|
|
/**
|
|
* 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);
|
|
|
|
/**
|
|
* Unescape text, call gotText() and reset parsed on success
|
|
* @param text The text to process
|
|
* @return True if there is no error
|
|
*/
|
|
bool processText(String& text);
|
|
|
|
/**
|
|
* 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 YATE_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 NoError if the child was successfully added
|
|
*/
|
|
virtual XmlSaxParser::Error addChild(XmlChild* child) = 0;
|
|
|
|
/**
|
|
* Append a new child of this XmlParent, release the object on failure
|
|
* @param child The child to append
|
|
* @param code Optional pointr to error code to be filled on failure
|
|
* @return The child on success, 0 on failure
|
|
*/
|
|
inline XmlChild* addChildSafe(XmlChild* child, XmlSaxParser::Error* code = 0) {
|
|
XmlSaxParser::Error err = addChild(child);
|
|
if (err != XmlSaxParser::NoError) {
|
|
TelEngine::destruct(child);
|
|
if (code)
|
|
*code = err;
|
|
}
|
|
return 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) = 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()
|
|
{ }
|
|
|
|
/**
|
|
* Check if at least one child element exists
|
|
* @return True if this parent has at least one child
|
|
*/
|
|
inline bool hasChildren() const
|
|
{ return getChildren().skipNull() != 0; }
|
|
};
|
|
|
|
/**
|
|
* A Document Object Model (DOM) parser for XML documents and fragments
|
|
* @short Document Object Model XML Parser
|
|
*/
|
|
class YATE_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
|
|
* @param takeOwnership True to take ownership of the fragment
|
|
*/
|
|
XmlDomParser(XmlParent* fragment, bool takeOwnership);
|
|
|
|
/**
|
|
* 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
|
|
bool m_ownData; // The DOM owns data
|
|
};
|
|
|
|
/**
|
|
* Xml Child for Xml document
|
|
* @short Xml Child
|
|
*/
|
|
class YATE_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; }
|
|
|
|
/**
|
|
* Replaces all ${paramname} with the corresponding parameters
|
|
* @param params List of parameters
|
|
*/
|
|
virtual void replaceParams(const NamedList& params)
|
|
{}
|
|
};
|
|
|
|
|
|
/**
|
|
* Xml Declaration for Xml document
|
|
* @short Xml Declaration
|
|
*/
|
|
class YATE_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 YATE_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<XmlChild*>(m_list.remove(false)); }
|
|
|
|
/**
|
|
* Remove the first XmlElement from list and returns it if completed
|
|
* @return XmlElement pointer or 0 if no XmlElement is found or the first one is not completed
|
|
*/
|
|
XmlElement* popElement();
|
|
|
|
/**
|
|
* 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(); }
|
|
|
|
/**
|
|
* Copy other fragment into this one
|
|
* @param other Fragment to copy
|
|
* @param parent Optional parent to set in copied children
|
|
*/
|
|
void copy(const XmlFragment& other, XmlParent* parent = 0);
|
|
|
|
/**
|
|
* 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;
|
|
|
|
/**
|
|
* Replaces all ${paramname} in fragment's children with the corresponding parameters
|
|
* @param params List of parameters
|
|
*/
|
|
void replaceParams(const NamedList& params);
|
|
|
|
/**
|
|
* 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
|
|
* @param noPrefix True to compare the tag without namespace prefix, false to
|
|
* include namespace prefix when comparing the given tag.
|
|
* This parameter is ignored if name is 0 or ns is not 0
|
|
* @return XmlElement pointer or 0 if not found
|
|
*/
|
|
static inline XmlElement* findElement(ObjList* list, const String* name, const String* ns,
|
|
bool noPrefix = true)
|
|
{ return getElement(list,name,ns,noPrefix); }
|
|
|
|
/**
|
|
* Retrieve first XML element from given list. Advance the list when found
|
|
* @param lst List of XmlChild
|
|
* @param name Optional element tag to match
|
|
* @param ns Optional element namespace to match
|
|
* @param noPrefix True to compare the tag without namespace prefix, false to
|
|
* include namespace prefix when comparing the given tag.
|
|
* This parameter is ignored if name is 0 or ns is not 0
|
|
* @return XmlElement pointer, NULL if not found
|
|
*/
|
|
static XmlElement* getElement(ObjList*& lst, const String* name = 0, const String* ns = 0,
|
|
bool noPrefix = true);
|
|
|
|
/**
|
|
* Retrieve first XML text from given list. Advance the list when found
|
|
* @param lst List of XmlChild
|
|
* @return XmlText pointer, NULL if not found
|
|
*/
|
|
static inline XmlText* getText(ObjList*& lst) {
|
|
XmlText* x = 0;
|
|
for (; lst && !x; lst = lst->skipNext())
|
|
x = (static_cast<XmlChild*>(lst->get()))->xmlText();
|
|
return x;
|
|
}
|
|
|
|
private:
|
|
static XmlElement* elementMatch(XmlElement* xml, const String* name, const String* ns,
|
|
bool noPrefix = true);
|
|
ObjList m_list; // The children list
|
|
};
|
|
|
|
/**
|
|
* Xml Document
|
|
* @short Xml Document
|
|
*/
|
|
class YATE_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 XML fragment outside the root element
|
|
* @param before True to retrieve the fragment holding children before root element,
|
|
* false to retrieve children after root
|
|
* @return Requested fragment's reference
|
|
*/
|
|
inline const XmlFragment& getFragment(bool before) const
|
|
{ return before ? m_beforeRoot : m_afterRoot; }
|
|
|
|
/**
|
|
* 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;
|
|
|
|
/**
|
|
* Take the root element from the document
|
|
* @param completed True to retrieve the root element if is not completed
|
|
* @return Root pointer or 0 if not found or is not completed
|
|
*/
|
|
inline XmlElement* takeRoot(bool completed = false)
|
|
{
|
|
XmlElement* r = root(completed);
|
|
if (r)
|
|
m_root = 0;
|
|
return r;
|
|
}
|
|
|
|
/**
|
|
* 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
|
|
* @param eoln End of line chars. Set it to NULL to ignore it. Empty string will be replaced by CR/LF
|
|
* @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 char* eoln = "\r\n") 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;
|
|
|
|
/**
|
|
* Replaces all ${paramname} in document's components with the corresponding parameters
|
|
* @param params List of parameters
|
|
*/
|
|
void replaceParams(const NamedList& params);
|
|
|
|
private:
|
|
XmlElement* m_root; // The root element
|
|
XmlFragment m_beforeRoot; // XML children before root (declaration ...)
|
|
String m_file; // The file name used on load
|
|
XmlFragment m_afterRoot; // XML children after root (comments, empty text)
|
|
};
|
|
|
|
|
|
/**
|
|
* Xml Element from a Xml document
|
|
* @short Xml Element
|
|
*/
|
|
|
|
class YATE_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);
|
|
|
|
/**
|
|
* Constructor. Create a new element with a text child
|
|
* @param name The name of the element
|
|
* @param value Element text child value
|
|
* @param complete False to build an incomplete element
|
|
*/
|
|
XmlElement(const char* name, const char* value, 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<const String&>(m_element); }
|
|
|
|
/**
|
|
* Set element's unprefixed tag, don't change namespace prefix
|
|
* @param s New element's tag
|
|
*/
|
|
void setUnprefixedTag(const String& s);
|
|
|
|
/**
|
|
* Retrieve the element's tag (without prefix)
|
|
* @return Element tag
|
|
*/
|
|
inline const String& getTag() const
|
|
{ return m_prefixed ? m_prefixed->name() : static_cast<const String&>(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 XmlElement child of this XmlElement
|
|
* @param name Optional name of the child
|
|
* @param ns Optional child namespace
|
|
* @param noPrefix True to compare the tag without namespace prefix, false to
|
|
* include namespace prefix when comparing the given tag.
|
|
* This parameter is ignored if name is 0 or ns is not 0
|
|
* @return The first child element meeting the requested conditions
|
|
*/
|
|
inline XmlElement* findFirstChild(const String* name = 0, const String* ns = 0,
|
|
bool noPrefix = true) const
|
|
{ return XmlFragment::findElement(getChildren().skipNull(),name,ns,noPrefix); }
|
|
|
|
/**
|
|
* Find the first XmlElement child of this XmlElement
|
|
* @param name Name of the child
|
|
* @param ns Optional child namespace
|
|
* @param noPrefix True to compare the tag without namespace prefix, false to
|
|
* include namespace prefix when comparing the given tag.
|
|
* This parameter is ignored if name is 0 or ns is not 0
|
|
* @return The first child element meeting the requested conditions
|
|
*/
|
|
inline XmlElement* findFirstChild(const String& name, const String* ns = 0,
|
|
bool noPrefix = true) const
|
|
{ return XmlFragment::findElement(getChildren().skipNull(),&name,ns,noPrefix); }
|
|
|
|
/**
|
|
* Finds next XmlElement child of this XmlElement
|
|
* @param prev Previous child
|
|
* @param name Optional name of the child
|
|
* @param ns Optional child namespace
|
|
* @param noPrefix True to compare the tag without namespace prefix, false to
|
|
* include namespace prefix when comparing the given tag.
|
|
* This parameter is ignored if name is 0 or ns is not 0
|
|
* @return The next found child if prev exists else the first
|
|
*/
|
|
inline XmlElement* findNextChild(const XmlElement* prev = 0, const String* name = 0,
|
|
const String* ns = 0, bool noPrefix = true) const {
|
|
if (!prev)
|
|
return findFirstChild(name,ns,noPrefix);
|
|
ObjList* start = getChildren().find(prev);
|
|
return start ? XmlFragment::findElement(start->skipNext(),name,ns,noPrefix) : 0;
|
|
}
|
|
|
|
/**
|
|
* Finds next XmlElement child of this XmlElement
|
|
* @param name Name of the child
|
|
* @param prev Previous child
|
|
* @param ns Optional child namespace
|
|
* @param noPrefix True to compare the tag without namespace prefix, false to
|
|
* include namespace prefix when comparing the given tag.
|
|
* This parameter is ignored if name is 0 or ns is not 0
|
|
* @return The next found child if prev exists else the first
|
|
*/
|
|
inline XmlElement* findNextChild(const String& name, const XmlElement* prev = 0,
|
|
const String* ns = 0, bool noPrefix = true) const
|
|
{ return findNextChild(prev,&name,ns,noPrefix); }
|
|
|
|
/**
|
|
* Retrieve a child's text
|
|
* @param name Name (tag) of the child
|
|
* @param ns Optional child namespace
|
|
* @param noPrefix True to compare the tag without namespace prefix, false to
|
|
* include namespace prefix when comparing the given tag.
|
|
* This parameter is ignored ns is not 0
|
|
* @return Pointer to child's text, 0 if the child was not found
|
|
*/
|
|
inline const String* childText(const String& name, const String* ns = 0,
|
|
bool noPrefix = true) const {
|
|
XmlElement* c = findFirstChild(&name,ns,noPrefix);
|
|
return c ? &(c->getText()) : 0;
|
|
}
|
|
|
|
/**
|
|
* Get first XmlChild of this XmlElement
|
|
* @return The first XmlChild found.
|
|
*/
|
|
XmlChild* getFirstChild();
|
|
|
|
/**
|
|
* @return The first XmlText found in this XmlElement children
|
|
*/
|
|
const String& getText() const;
|
|
|
|
/**
|
|
* Set text for first XmlText element found in this XmlElement's children
|
|
* If child text element does not exist, create it and append it to the element's children.
|
|
* @param text Text to set to the XmlElement. If null, the first found XmlText element
|
|
* will be deleted.
|
|
* @return The set XmlText if text was set, null if an XmlText was deleted
|
|
*/
|
|
XmlText* setText(const char* text);
|
|
|
|
/**
|
|
* 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
|
|
* @param list Destination list
|
|
* @param 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;
|
|
|
|
/**
|
|
* Set element attributes from a list of parameters
|
|
* @param list List of attributes
|
|
* @param prefix Add only the attributes that start with this prefix. =
|
|
* If NULL, it will set as attributes the whole parameter list
|
|
* @param skipPrefix Skip over the prefix when building attribute name
|
|
*/
|
|
void setAttributes(NamedList& list, const String& prefix, bool skipPrefix = true);
|
|
|
|
/**
|
|
* 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());
|
|
|
|
/**
|
|
* Replaces all ${paramname} in element's attributes and children with the
|
|
* corresponding parameters
|
|
* @param params List of parameters
|
|
*/
|
|
virtual void replaceParams(const NamedList& params);
|
|
|
|
/**
|
|
* 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); }
|
|
|
|
/**
|
|
* Build an XML element from a list parameter.
|
|
* Parameter name will be set in a 'name' attribute.
|
|
* Parameter value will be set in a 'value' attribute
|
|
* Handle NamedPointer parameters carrying DataBlock, NamedList and
|
|
* XmlElement objects (a 'type' attribute is added to the created element).
|
|
* DataBlock: Encode using BASE64 and add it as element text
|
|
* NamedList: The name is added as element text. The function is called
|
|
* again for each list parameter
|
|
* XmlElement: Added as child to newly created element
|
|
* @param param The parameter to convert
|
|
* @param tag XmlElement tag
|
|
* @param copyXml True to copy XmlElement objects instead of just remove
|
|
* them from the parameter
|
|
* @return XmlElement pointer or 0 on failure
|
|
*/
|
|
static XmlElement* param2xml(NamedString* param, const String& tag,
|
|
bool copyXml = false);
|
|
|
|
/**
|
|
* Build a list parameter from xml element
|
|
* See @ref param2xml for more info
|
|
* @param xml The XML element to process
|
|
* @param tag Child XmlElement tag to handle
|
|
* @param copyXml True to copy XmlElement objects instead of just remove
|
|
* them from parent
|
|
* @return NamedString pointer or 0 on failure
|
|
*/
|
|
static NamedString* xml2param(XmlElement* xml, const String* tag,
|
|
bool copyXml = false);
|
|
|
|
/**
|
|
* Build and add list parameters from XML element children.
|
|
* Each parameter will be taken from 'name' and 'value' attributes.
|
|
* See @ref param2xml for more info
|
|
* @param list Destination list
|
|
* @param parent The XML element to process
|
|
* @param tag Child XmlElement tag to handle
|
|
* @param copyXml True to copy XmlElement objects instead of just remove
|
|
* them from parent
|
|
*/
|
|
static void xml2param(NamedList& list, XmlElement* parent, const String* tag,
|
|
bool copyXml = false);
|
|
|
|
/**
|
|
* 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 YATE_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 YATE_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 YATE_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; }
|
|
|
|
/**
|
|
* Set the text
|
|
* @param text Text to set in this XmlText
|
|
*/
|
|
inline void setText(const char* text)
|
|
{ m_text = 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; }
|
|
|
|
/**
|
|
* Helper method to check if the text held by this XmlText contains only spaces
|
|
* @return False if the text contains non space characters.
|
|
*/
|
|
bool onlySpaces();
|
|
|
|
/**
|
|
* Replaces all ${paramname} in text with the corresponding parameters
|
|
* @param params List of parameters
|
|
*/
|
|
virtual void replaceParams(const NamedList& params);
|
|
|
|
private:
|
|
String m_text; // The text
|
|
};
|
|
|
|
class YATE_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
|
|
};
|
|
|
|
|
|
// Internal
|
|
class XPathParseData;
|
|
class XPathPredicate;
|
|
class XPathStep;
|
|
|
|
/**
|
|
* This class holds an XML Path
|
|
* @short XML Path holder
|
|
*/
|
|
class YATE_API XPath : public String
|
|
{
|
|
YCLASS(XPath,String)
|
|
public:
|
|
/**
|
|
* Path flags
|
|
*/
|
|
enum Flags {
|
|
LateParse = 0x0001, // Don't try to parse in constructor
|
|
StrictParse = 0x0002, // Strict parse
|
|
// - Don't allow spaces at step start
|
|
// - Don't ignore duplicate index predicate (not specified in spec but common sense)
|
|
IgnoreEmptyResult = 0x0004, // Don't check always empty result path (avoid error: EEmptyResult)
|
|
NoXmlNameCheck = 0x0008, // Don't validate XML names (tag and attribute)
|
|
// Internal
|
|
FInternal = 0xff00, // Internal flags mask
|
|
FAbsolute = 0x0100, // Absolute path
|
|
};
|
|
|
|
/**
|
|
* Find result type
|
|
*/
|
|
enum Find {
|
|
FindXml = 0x01,
|
|
FindText = 0x02,
|
|
FindAttr = 0x04,
|
|
FindAny = FindXml | FindText | FindAttr
|
|
};
|
|
|
|
/**
|
|
* Error (status) codes
|
|
*/
|
|
enum Status {
|
|
NoError = 0,
|
|
// Syntax errors
|
|
EEmptyItem, // Empty path item
|
|
ESyntax, // Generic syntax error
|
|
// Semantic errors
|
|
ERange, // Out of range value
|
|
ESemantic, // Generic semantic error
|
|
// Oher errors
|
|
EEmptyResult, // Path will always produce an empty result
|
|
NotParsed, // Path not parsed, never returned as error
|
|
};
|
|
|
|
/**
|
|
* Constructor
|
|
* @param value Initial value
|
|
* @param flags Path flags
|
|
*/
|
|
XPath(const char* value = 0, unsigned int flags = 0);
|
|
|
|
/**
|
|
* Copy constructor
|
|
* @param other Object to copy
|
|
*/
|
|
XPath(const XPath& other);
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~XPath();
|
|
|
|
/**
|
|
* Check if the parth is absolute
|
|
* @return True if the path is absolute, false otherwise
|
|
*/
|
|
inline bool absolute() const
|
|
{ return 0 != (m_flags & FAbsolute); }
|
|
|
|
/**
|
|
* Retrieve the path parse error
|
|
* @return 0 on success, failed code otherwise
|
|
*/
|
|
inline unsigned int status() const
|
|
{ return m_status; }
|
|
|
|
/**
|
|
* Retrieve the failed to parse item index (0 based)
|
|
* @return 0 based failed to parse item index
|
|
*/
|
|
inline unsigned int errorItem() const
|
|
{ return m_errorItem; }
|
|
|
|
/**
|
|
* Retrieve the additional path parse error string
|
|
* @return Parse error string (may be empty)
|
|
*/
|
|
inline const String& error() const
|
|
{ return m_error; }
|
|
|
|
/**
|
|
* Describe the error
|
|
* @param buf Destination buffer
|
|
* @return Destination buffer reference
|
|
*/
|
|
inline String& describeError(String& buf) const {
|
|
if (!status())
|
|
return buf;
|
|
buf << "item=" << m_errorItem << " status=" << m_status;
|
|
const char* tmp = error() ? error().c_str() : lookup(m_status,dictErrors());
|
|
if (tmp)
|
|
buf << " (" << tmp << ")";
|
|
return buf;
|
|
}
|
|
|
|
/**
|
|
* Parse the path if not already done
|
|
* @return 0 on success, failed code otherwise
|
|
*/
|
|
inline unsigned int parse() {
|
|
if (NotParsed == status())
|
|
parsePath();
|
|
return status();
|
|
}
|
|
|
|
/**
|
|
* Find in xml using this path
|
|
* @param xml XML element to search in
|
|
* @param what Flags indicating data to match
|
|
* @param list Optional pointer to list to be filled with multiple elements matching the path
|
|
* Set it to NULL if single element is requested
|
|
* Filled objects may be XmlElement, String (XmlText contents) or NamedString (attribute)
|
|
* Objects set in it have autodelete disabled
|
|
* @return First found item, NULL if not found
|
|
*/
|
|
inline const GenObject* find(const XmlElement& xml, unsigned int what, ObjList* list = 0) const {
|
|
if (status() || 0 == (FindAny & what))
|
|
return 0;
|
|
const GenObject* res = 0;
|
|
unsigned int total = 0;
|
|
find(total,xml,res,list,what,0,0,absolute());
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* Find XML element(s)
|
|
* @param xml XML element to search in
|
|
* @param list Optional pointer to list to be filled with multiple elements matching the path
|
|
* Set it to NULL if single element is requested
|
|
* Objects set in it have autodelete disabled
|
|
* @return First found item, NULL if not found.
|
|
*/
|
|
inline XmlElement* findXml(const XmlElement& xml, ObjList* list = 0) const
|
|
{ return (XmlElement*)find(xml,FindXml,list); }
|
|
|
|
/**
|
|
* Find XML text(s)
|
|
* @param xml XML element to search in
|
|
* @param list Optional pointer to list to be filled with multiple texts matching the path
|
|
* Set it to NULL if single text is requested
|
|
* Objects set in it have autodelete disabled
|
|
* @return First found item, NULL if not found.
|
|
*/
|
|
inline const String* findText(const XmlElement& xml, ObjList* list = 0) const
|
|
{ return (const String*)find(xml,FindText,list); }
|
|
|
|
/**
|
|
* Dump path items to string
|
|
* Build a canonical (spaces stripped ...) string: dump(buf,true,"/",absolute())
|
|
* @param buf Destination buffer
|
|
* @param escape Escape strings
|
|
* @param itemSep Item separator
|
|
* @param sepFirst Add item separator before first item
|
|
* @return Given buffer reference
|
|
*/
|
|
String& dump(String& buf, bool escape = true, const char* itemSep = "\r\n",
|
|
bool sepFirst = true) const;
|
|
|
|
/**
|
|
* Dump path items string to ObjList
|
|
* @param lst Destination list
|
|
* @param escape Escape strings
|
|
*/
|
|
void dump(ObjList& lst, bool escape = true) const;
|
|
|
|
/**
|
|
* Escape a string and add quoted value to buffer
|
|
* @param buf Destination buffer
|
|
* @param str String to escape
|
|
* @param quot Character to use for quoting. Use " if not " or '
|
|
* @param literal Escape as literal (used in comparison operators) or
|
|
* XML string (used in function parameters)
|
|
* @return Destination buffer reference
|
|
*/
|
|
static String& escape(String& buf, const String& str, char quot = '"', bool literal = true);
|
|
|
|
/**
|
|
* Retrieve the number of maximum allowed predicates in a path step
|
|
* @return Maximum allowed predicates in a path step
|
|
*/
|
|
static unsigned int maxStepPredicates();
|
|
|
|
/**
|
|
* Retrieve the dictionary containing the error strings
|
|
* @return Valid dictionary pointer
|
|
*/
|
|
static const TokenDict* dictErrors();
|
|
|
|
protected:
|
|
/**
|
|
* Called whenever the String value changed.
|
|
* Reset data, parse the path
|
|
*/
|
|
virtual void changed();
|
|
|
|
/**
|
|
* Parse the path
|
|
*/
|
|
void parsePath();
|
|
|
|
/**
|
|
* Reset data
|
|
*/
|
|
void reset();
|
|
|
|
private:
|
|
int find(unsigned int& total, const XmlElement& src, const GenObject*& res, ObjList* list,
|
|
unsigned int what, ObjList* crtItem = 0, unsigned int step = 0, bool absolute = false) const;
|
|
int getText(unsigned int& total, const XmlElement& xml, const XPathStep* step,
|
|
unsigned int& resultIdx, const GenObject*& res, ObjList* list) const;
|
|
bool parseStepPredicate(XPathParseData& data, XPathPredicate* pred);
|
|
bool checkStepPredicate(XPathParseData& data, XPathStep* step, XPathPredicate* pred);
|
|
bool setStatus(unsigned int code, unsigned int itemIdx = 0, const char* error = 0,
|
|
XPathParseData* data = 0);
|
|
|
|
unsigned int m_flags;
|
|
ObjList m_items;
|
|
unsigned int m_status;
|
|
unsigned int m_errorItem;
|
|
String m_error;
|
|
};
|
|
|
|
}; // namespace TelEngine
|
|
|
|
#endif /* __YATEXML_H */
|
|
|
|
/* vi: set ts=8 sw=4 sts=4 noet: */
|