Files
simgear/simgear/xml/easyxml.hxx
2016-07-03 23:41:07 +01:00

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