/*************************************************************************** * Copyright (c) Jürgen Riegel (juergen.riegel@web.de) * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #ifndef BASE_READER_H #define BASE_READER_H #include #include #include #include #include #include "FileInfo.h" #include "Writer.h" namespace zipios { class ZipInputStream; } XERCES_CPP_NAMESPACE_BEGIN class DefaultHandler; class SAX2XMLReader; XERCES_CPP_NAMESPACE_END namespace Base { /** The XML reader class * This is an important helper class for the store and retrieval system * of objects in FreeCAD. These classes mainly inherit the App::Persitance * base class and implement the Restore() method. * \par * The reader gets mainly initialized by the App::Document on retrieving a * document out of a file. From there subsequently the Restore() method will * by called on all object stored. * \par * A simple example is the Restore of App::PropertyString: * \code void PropertyString::Save (short indent,std::ostream &str) { str << "" ; } void PropertyString::Restore(Base::Reader &reader) { // read my Element reader.readElement("String"); // get the value of my Attribute _cValue = reader.getAttribute("value"); } * \endcode * \par * An more complicated example is the retrieval of the App::PropertyContainer: * \code void PropertyContainer::Save (short indent,std::ostream &str) { std::map Map; getPropertyMap(Map); str << ind(indent) << "" << endl; std::map::iterator it; for(it = Map.begin(); it != Map.end(); ++it) { str << ind(indent+1) << "first << "\" type=\"" << it->second->getTypeId().getName() << "\">" ; it->second->Save(indent+2,str); str << "" << endl; } str << ind(indent) << "" << endl; } void PropertyContainer::Restore(Base::Reader &reader) { reader.readElement("Properties"); int Cnt = reader.getAttributeAsInteger("Count"); for(int i=0 ;iRestore(reader); reader.readEndElement("Property"); } reader.readEndElement("Properties"); } * \endcode * \see Base::Persistence * \author Juergen Riegel */ class BaseExport XMLReader : public XERCES_CPP_NAMESPACE_QUALIFIER DefaultHandler { public: /// open the file and read the first element XMLReader(const char* FileName, std::istream&); ~XMLReader(); bool isValid() const { return _valid; } bool isVerbose() const { return _verbose; } void setVerbose(bool on) { _verbose = on; } /** @name Parser handling */ //@{ /// get the local name of the current Element const char* localName(void) const; /// read until a start element is found (\) or start-end element (\) (with special name if given) void readElement (const char* ElementName=0); /// read until an end element is found (with special name if given) void readEndElement(const char* ElementName=0); /// read until characters are found void readCharacters(void); /// read binary file void readBinFile(const char*); //@} /** @name Attribute handling */ //@{ /// get the number of attributes of the current element unsigned int getAttributeCount(void) const; /// check if the read element has a special attribute bool hasAttribute(const char* AttrName) const; /// return the named attribute as an interer (does type checking) long getAttributeAsInteger(const char* AttrName) const; unsigned long getAttributeAsUnsigned(const char* AttrName) const; /// return the named attribute as a double floating point (does type checking) double getAttributeAsFloat(const char* AttrName) const; /// return the named attribute as a double floating point (does type checking) const char* getAttribute(const char* AttrName) const; //@} /** @name additional file reading */ //@{ /// add a read request of a persistent object const char *addFile(const char* Name, Base::Persistence *Object); /// process the requested file writes void readFiles(zipios::ZipInputStream &zipstream) const; /// get all registered file names const std::vector& getFilenames() const; bool isRegistered(Base::Persistence *Object) const; virtual void addName(const char*, const char*); virtual const char* getName(const char*) const; virtual bool doNameMapping() const; //@} /// Schema Version of the document int DocumentSchema; /// Version of FreeCAD that wrote this document std::string ProgramVersion; /// Version of the file format int FileVersion; protected: /// read the next element bool read(void); // ----------------------------------------------------------------------- // Handlers for the SAX ContentHandler interface // ----------------------------------------------------------------------- /** @name Content handler */ //@{ virtual void startDocument(); virtual void endDocument(); virtual void startElement(const XMLCh* const uri, const XMLCh* const localname, const XMLCh* const qname, const XERCES_CPP_NAMESPACE_QUALIFIER Attributes& attrs); virtual void endElement (const XMLCh* const uri, const XMLCh *const localname, const XMLCh *const qname); #if (XERCES_VERSION_MAJOR == 2) virtual void characters (const XMLCh* const chars, const unsigned int length); virtual void ignorableWhitespace(const XMLCh* const chars, const unsigned int length); #else virtual void characters (const XMLCh* const chars, const XMLSize_t length); virtual void ignorableWhitespace(const XMLCh* const chars, const XMLSize_t length); #endif //@} /** @name Lexical handler */ //@{ virtual void startCDATA (); virtual void endCDATA (); //@} /** @name Document handler */ //@{ virtual void resetDocument(); //@} // ----------------------------------------------------------------------- // Handlers for the SAX ErrorHandler interface // ----------------------------------------------------------------------- /** @name Error handler */ //@{ void warning(const XERCES_CPP_NAMESPACE_QUALIFIER SAXParseException& exc); void error(const XERCES_CPP_NAMESPACE_QUALIFIER SAXParseException& exc); void fatalError(const XERCES_CPP_NAMESPACE_QUALIFIER SAXParseException& exc); void resetErrors(); //@} int Level; std::string LocalName; std::string Characters; unsigned int CharacterCount; std::map AttrMap; typedef std::map AttrMapType; enum { None = 0, Chars, StartDocument, EndDocument, StartElement, StartEndElement, EndElement, StartCDATA, EndCDATA } ReadType; FileInfo _File; XERCES_CPP_NAMESPACE_QUALIFIER SAX2XMLReader* parser; XERCES_CPP_NAMESPACE_QUALIFIER XMLPScanToken token; bool _valid; bool _verbose; struct FileEntry { std::string FileName; Base::Persistence *Object; }; std::vector FileList; std::vector FileNames; }; class BaseExport Reader : public std::istream { public: Reader(std::istream&, const std::string&, int version); std::istream& getStream(); std::string getFileName() const; int getFileVersion() const; private: std::istream& _str; std::string _name; int fileVersion; }; } #endif