521 lines
15 KiB
C++
521 lines
15 KiB
C++
/**
|
|
* \file easyxml.hxx
|
|
* Declarations for the SimGear XML parser.
|
|
* Written by David Megginson, 2000-2001
|
|
* This file is in the Public Domain, and comes with NO WARRANTY of any kind.
|
|
*/
|
|
|
|
#ifndef __EASYXML_HXX
|
|
#define __EASYXML_HXX
|
|
|
|
#include <simgear/compiler.h>
|
|
#include <simgear/structure/exception.hxx>
|
|
|
|
#include <iosfwd>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
class SGPath;
|
|
|
|
typedef struct XML_ParserStruct* XML_Parser;
|
|
|
|
/**
|
|
* Interface for XML attributes.
|
|
*
|
|
* This interface is used to provide a list of attributes to the
|
|
* application. The interface is a pure abstract class so that
|
|
* different implementations can be substituted for the sake of
|
|
* efficiency.
|
|
*
|
|
* @see XMLAttributesDefault
|
|
*/
|
|
class XMLAttributes
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Constructor.
|
|
*/
|
|
XMLAttributes ();
|
|
|
|
|
|
/**
|
|
* Destructor.
|
|
*/
|
|
virtual ~ XMLAttributes ();
|
|
|
|
|
|
/**
|
|
* Get the number of attributes present.
|
|
*
|
|
* @return The number of attributes in the list (may be 0).
|
|
*/
|
|
virtual int size () const = 0;
|
|
|
|
|
|
/**
|
|
* Get the name of an attribute by index.
|
|
*
|
|
* The index must be less than the size of the list and greater
|
|
* than or equal to zero.
|
|
*
|
|
* @param i The index of the attribute (zero-based).
|
|
* @see #size
|
|
*/
|
|
virtual const char * getName (int i) const = 0;
|
|
|
|
|
|
/**
|
|
* Get the string value of an attribute by index.
|
|
*
|
|
* The index must be less than the size of the list and greater
|
|
* than or equal to zero.
|
|
*
|
|
* @param i The index of the attribute (zero-based).
|
|
* @see #size
|
|
*/
|
|
virtual const char * getValue (int i) const = 0;
|
|
|
|
|
|
/**
|
|
* Look up the index of an attribute by name.
|
|
*
|
|
* Attribute names must be unique. This method will return
|
|
* an index that can be used with the {@link #getValue(const char *)}
|
|
* method if the attribute is found.
|
|
*
|
|
* @param name The name of the attribute.
|
|
* @return The index of the attribute with the name specified,
|
|
* or -1 if no such attribute is present in the list.
|
|
*/
|
|
virtual int findAttribute (const char * name) const;
|
|
|
|
|
|
/**
|
|
* Test whether an attribute is present.
|
|
*
|
|
* @param name The name of the attribute.
|
|
* @return true if an attribute with the specified name is present
|
|
* in the attribute list, false otherwise.
|
|
*/
|
|
virtual bool hasAttribute (const char * name) const;
|
|
|
|
|
|
/**
|
|
* Look up the value of an attribute by name.
|
|
*
|
|
* This method provides a convenient short-cut to invoking
|
|
* {@link #findAttribute} and {@link #getValue(const char *)}.
|
|
*
|
|
* @param name The name of the attribute to look up.
|
|
* @return The attribute's value as a string, or 0 if no
|
|
* attribute was found with the name specified.
|
|
*/
|
|
virtual const char * getValue (const char * name) const;
|
|
};
|
|
|
|
|
|
/**
|
|
* Default mutable attributes implementation.
|
|
*
|
|
* This class provides a default implementation of the {@link
|
|
* XMLAttributes} interface. The implementation is mutable, so
|
|
* that it is possible to modify the attribute list when necessary.
|
|
* This class is particularly useful for taking a snapshot of
|
|
* an attribute list during parsing.
|
|
*
|
|
* @see XMLAttributes
|
|
*/
|
|
class XMLAttributesDefault : public XMLAttributes
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Default constructor.
|
|
*/
|
|
XMLAttributesDefault ();
|
|
|
|
|
|
/**
|
|
* Copy constructor.
|
|
*
|
|
* This constructor is especially useful for taking a static
|
|
* snapshot of an attribute list for later use.
|
|
*
|
|
* @param atts The attribute list to copy.
|
|
*/
|
|
XMLAttributesDefault (const XMLAttributes & atts);
|
|
|
|
|
|
/**
|
|
* Destructor.
|
|
*/
|
|
virtual ~XMLAttributesDefault ();
|
|
|
|
|
|
/**
|
|
* Count the attributes in the list.
|
|
*/
|
|
virtual int size () const;
|
|
|
|
|
|
/**
|
|
* Get the name of an attribute by index.
|
|
*/
|
|
virtual const char * getName (int i) const;
|
|
|
|
|
|
/**
|
|
* Get the value of an attribute by index.
|
|
*/
|
|
virtual const char * getValue (int i) const;
|
|
|
|
|
|
/**
|
|
* Add an attribute to an attribute list.
|
|
*
|
|
* The name is required to be unique in the list; the value is not.
|
|
*
|
|
* @param name The name of the attribute to add.
|
|
* @param value The value of the attribute to add.
|
|
*/
|
|
virtual void addAttribute (const char * name, const char * value);
|
|
|
|
|
|
/**
|
|
* Set an attribute name by index.
|
|
*
|
|
* This method will not extend the list; the attribute must
|
|
* already exist.
|
|
*
|
|
* @param i The index of the attribute (zero-based).
|
|
* @param name The new name.
|
|
*/
|
|
virtual void setName (int i, const char * name);
|
|
|
|
|
|
/**
|
|
* Set an attribute value by index.
|
|
*
|
|
* This method will not extend the list; the attribute must
|
|
* already exist.
|
|
*
|
|
* @param i The index of the attribute (zero-based).
|
|
* @param value The new value.
|
|
*/
|
|
virtual void setValue (int i, const char * value);
|
|
|
|
|
|
/**
|
|
* Set an attribute value by name.
|
|
*
|
|
* This method will not extend the list; the attribute must
|
|
* already exist.
|
|
*
|
|
* @param name The name of the attribute that will have the new
|
|
* value.
|
|
* @param value The new value.
|
|
*/
|
|
virtual void setValue (const char * name, const char * value);
|
|
|
|
private:
|
|
std::vector<std::string> _atts;
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// Attribute list wrapper for Expat.
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
class ExpatAtts : public XMLAttributes
|
|
{
|
|
public:
|
|
ExpatAtts (const char ** atts) : _atts(atts) {}
|
|
|
|
virtual int size () const;
|
|
virtual const char * getName (int i) const;
|
|
virtual const char * getValue (int i) const;
|
|
|
|
virtual const char * getValue (const char * name) const;
|
|
private:
|
|
const char ** _atts;
|
|
};
|
|
|
|
|
|
/**
|
|
* Visitor class for an XML document.
|
|
*
|
|
* This interface uses the Visitor pattern. The XML parser walks
|
|
* through the XML document and invokes the appropriate method in
|
|
* this visitor for each piece of markup it finds. By default,
|
|
* the methods do nothing; the application must subclass the visitor
|
|
* and override the methods for the events it's interested in.
|
|
* All applications are required to provide an implementation
|
|
* for the {@link #error} callback.
|
|
*/
|
|
class XMLVisitor
|
|
{
|
|
public:
|
|
/// Constructor
|
|
XMLVisitor() : parser(0), line(-1), column(-1) {}
|
|
|
|
/**
|
|
* Virtual destructor.
|
|
*/
|
|
virtual ~XMLVisitor () {}
|
|
|
|
|
|
/**
|
|
* Callback for the start of an XML document.
|
|
*
|
|
* The XML parser will invoke this method once, at the beginning of
|
|
* the XML document, before any other methods are invoked. The
|
|
* application can use this callback to set up data structures,
|
|
* open files, etc.
|
|
*
|
|
* @see #endXML
|
|
*/
|
|
virtual void startXML () {}
|
|
|
|
|
|
/**
|
|
* Callback for the end of an XML document.
|
|
*
|
|
* The XML parser will invoke this method once, at the end of the
|
|
* XML document, after all other methods are invoked, and only
|
|
* if there have been no parsing errors. The application can use
|
|
* this callback to close or write files, finalize data structures,
|
|
* and so on, but the application will need to be prepared to
|
|
* clean up any resources without this callback in the event of
|
|
* an error.
|
|
*
|
|
* @see #startXML
|
|
* @see #error
|
|
*/
|
|
virtual void endXML () {}
|
|
|
|
|
|
/**
|
|
* Callback for the start of an XML element.
|
|
*
|
|
* The XML parser will invoke this method at the beginning of every
|
|
* XML element. Start and end element calls will be balanced
|
|
* and properly nested: every element has both a start and end
|
|
* callback (even if it was specified with an XML empty element tag),
|
|
* there is exactly one root element, and every element must end
|
|
* before its parent does. Elements may not overlap.
|
|
* Note that the attribute list provided is volatile; it's contents
|
|
* are not guaranteed to persist after the end of the callback.
|
|
* If the application needs to keep a copy of the attribute list,
|
|
* it can make the copy with the {@link XMLAttributesDefault} class.
|
|
*
|
|
* @param name The name of the element that is starting (not null).
|
|
* @param atts The element's attributes (not null).
|
|
* @see #endElement
|
|
*/
|
|
virtual void startElement (const char * name, const XMLAttributes &atts) {}
|
|
|
|
|
|
/**
|
|
* Callback for the end of an XML element.
|
|
*
|
|
* The XML parser will invoke this method at the end of every XML element.
|
|
*
|
|
* @param name The name of the element that is ending (not null).
|
|
* @see #startElement
|
|
*/
|
|
virtual void endElement (const char * name) {}
|
|
|
|
|
|
/**
|
|
* Callback for a chunk of character data.
|
|
*
|
|
* The XML parser will invoke this method once for every chunk of
|
|
* character data in the XML document, including whitespace
|
|
* separating elements (as required by the XML recommendation).
|
|
* Note that character data may be chunked arbitrarily: the
|
|
* character data content of an element may be returned in one
|
|
* large chunk or several consecutive smaller chunks.
|
|
*
|
|
* @param s A pointer to the beginning of the character data (not null).
|
|
* @param length The number of characters in the chunk (may
|
|
* be zero).
|
|
*/
|
|
virtual void data (const char * s, int length) {}
|
|
|
|
|
|
/**
|
|
* Callback for an XML processing instruction.
|
|
*
|
|
* The XML parser will invoke this method once for every processing
|
|
* instruction in the XML document. Note that the XML declaration
|
|
* and the Text declaration are NOT PROCESSING INSTRUCTIONS and
|
|
* will not be reported through this callback. Processing
|
|
* instructions are not all that useful, but the XML recommendation
|
|
* requires that they be reported. Most applications can safely
|
|
* ignore this callback and use the empty default implementation.
|
|
*
|
|
* @param target The processing instruction target (not null).
|
|
* @param data The processing instruction data (not null).
|
|
*/
|
|
virtual void pi (const char * target, const char * data) {}
|
|
|
|
|
|
/**
|
|
* Callback for an XML parsing warning.
|
|
*
|
|
* The XML parser will use this callback to report any non-fatal warnings
|
|
* during parsing. It is the responsibility of the application to
|
|
* deal with the warning in some appropriate way.
|
|
*
|
|
* @param message The warning message from the parser.
|
|
* @param line The number of the line that generated the warning.
|
|
* @param column The character position in the line that generated
|
|
* the warning.
|
|
*/
|
|
virtual void warning (const char * message, int line, int column) {}
|
|
|
|
/** Set the path to the file that is parsed.
|
|
*
|
|
* This method will be called to store the path to the parsed file. Note that
|
|
* the XML parser makes no use of this copy of the path. The intent is
|
|
* to be capable of refering to the path to the parsed file if needed.
|
|
*
|
|
* @param _path The path to the parsed file.
|
|
* @see #getPath
|
|
*/
|
|
void setPath(const std::string& _path) { path = _path; }
|
|
|
|
/** Get the path to the parsed file.
|
|
*
|
|
* This method will be called if the application needs to access the path to
|
|
* the parsed file. This information is typically needed if an error is found
|
|
* so the file where it occurred can be retrieved to help the user locate the
|
|
* error.
|
|
*
|
|
* @return the path to the parsed file.
|
|
* @see #setPath
|
|
*/
|
|
const std::string& getPath(void) const { return path; }
|
|
|
|
/** Save the current position in the parsed file.
|
|
*
|
|
* This method will be called to save the position at which the file is
|
|
* currently parsed. Note that the XML parser makes no use of that
|
|
* information. The intent is to be capable of refering to the position in
|
|
* the parsed file if needed.
|
|
*
|
|
* @see #getColumn
|
|
* @see #getLine
|
|
*/
|
|
void savePosition(void);
|
|
|
|
/** Get the saved column number in the parsed file.
|
|
*
|
|
* This method will be called if the application needs to get the column
|
|
* number that has been saved during the last call to savePosition(). This
|
|
* information is typically needed if an error is found so the position at
|
|
* which it occurred can be retrieved to help the user locate the error.
|
|
*
|
|
* @return the save column number.
|
|
* @see #savePosition
|
|
*/
|
|
int getColumn(void) const { return column; }
|
|
|
|
/** Get the saved line number in the parsed file.
|
|
*
|
|
* This method will be called if the application needs to get the line
|
|
* number that has been saved during the last call to savePosition(). This
|
|
* information is typically needed if an error is found so the position at
|
|
* which it occurred can be retrieved to help the user locate the error.
|
|
*
|
|
* @return the save line number.
|
|
* @see #savePosition
|
|
*/
|
|
int getLine(void) const { return line; }
|
|
|
|
/** Set the XML parser.
|
|
*
|
|
* This method will be called so the #XMLVisitor instance can internally use
|
|
* the XML parser for its housekeeping. The intent is that #XMLVisitor will
|
|
* only call the reporting functions of the XML parser and will not interfer
|
|
* with the XML parser current state. Doing otherwise will result in an
|
|
* unpredictable behavior of the XML parser.
|
|
*
|
|
* @param _parser the XML parser
|
|
*/
|
|
void setParser(XML_Parser _parser) { parser = _parser; }
|
|
private:
|
|
XML_Parser parser;
|
|
std::string path;
|
|
int line, column;
|
|
};
|
|
|
|
|
|
/**
|
|
* @relates XMLVisitor
|
|
* Read an XML document.
|
|
*
|
|
* This function reads an XML document from the input stream provided,
|
|
* and invokes the callback methods in the visitor object to pass the
|
|
* parsing events back to the application. When this function
|
|
* returns, the parser will have reported all of the data in the XML
|
|
* document to the application through the visitor callback methods,
|
|
* and XML processing will be complete.
|
|
*
|
|
* @param input The byte input stream containing the XML document.
|
|
* @param visitor An object that contains callbacks for XML parsing
|
|
* events.
|
|
* @param path A string describing the original path of the resource.
|
|
* @exception Throws sg_io_exception or sg_xml_exception if there
|
|
* is a problem reading the file.
|
|
* @see XMLVisitor
|
|
*/
|
|
extern void readXML (std::istream &input, XMLVisitor &visitor,
|
|
const std::string &path="");
|
|
|
|
|
|
/**
|
|
* @relates XMLVisitor
|
|
* Read an XML document.
|
|
*
|
|
* This function reads an XML document from the input stream provided,
|
|
* and invokes the callback methods in the visitor object to pass the
|
|
* parsing events back to the application. When this function
|
|
* returns, the parser will have reported all of the data in the XML
|
|
* document to the application through the visitor callback methods,
|
|
* and XML processing will be complete.
|
|
*
|
|
* @param path The file name of the XML resource.
|
|
* @param visitor An object that contains callbacks for XML parsing
|
|
* events.
|
|
* @exception Throws sg_io_exception or sg_xml_exception if there
|
|
* is a problem reading the file.
|
|
* @see XMLVisitor
|
|
*/
|
|
extern void readXML (const SGPath &path, XMLVisitor &visitor);
|
|
|
|
|
|
/**
|
|
* @relates XMLVisitor
|
|
* Read an XML document.
|
|
*
|
|
* This function reads an XML document from the buffer provided,
|
|
* and invokes the callback methods in the visitor object to pass the
|
|
* parsing events back to the application. When this function
|
|
* returns, the parser will have reported all of the data in the XML
|
|
* document to the application through the visitor callback methods,
|
|
* and XML processing will be complete.
|
|
*
|
|
* @param buf The xml data buffer.
|
|
* @param size The size of the data buffer in bytes
|
|
* @param visitor An object that contains callbacks for XML parsing
|
|
* events.
|
|
* @exception Throws sg_io_exception or sg_xml_exception if there
|
|
* is a problem reading the file.
|
|
* @see XMLVisitor
|
|
*/
|
|
extern void readXML (const char *buf, const int size, XMLVisitor &visitor);
|
|
|
|
|
|
#endif // __EASYXML_HXX
|