Advanced   Java   Services Parsen von XML-Dateien mit Xerces unter Visual Studio Back Next Up Home


Herunterladen des Xerces Pakets

Das Xerces Paket ist eine Sammlung von Dateien, die einen objektorientierten Zugriff auf XML-Dateien ermöglichen und wird von der Apache Software Foundation zur Verfügung gestellt. In der Übersicht auf http://xerces.apache.org/xerces-c/index.html heißt es:

"Xerces-C++ is a validating XML parser written in a portable subset of C++. Xerces-C++ makes it easy to give your application the ability to read and write XML data. A shared library is provided for parsing, generating, manipulating, and validating XML documents using the DOM, SAX, and SAX2 APIs."

Xerces liegt in gepackter Form unter http://xerces.apache.org/xerces-c/download.cgi zum Herunterladen bereit. Beim Entpacken wird je nach Versionsnummer ein Verzeichnis etwa mit dem Namen xerces-c-3.1.1-x86-windows-vc-8.0 angelegt, das alle notwendigen Dateien enthält.


Der SAX2 Parser

Das nachfolgende Beispiel bringt eine Schablone, mit der man mit Hilfe von SAX lesend auf XML-Dateien zugreifen kann. Interessanterweise wurde dieser Parser in Anlehnung an den SAX Parser von Java entwickelt. Auf  http://xerces.apache.org/xerces-c/program-sax2-3.html#UsingSAX2API  heißt es

The SAX2 API for XML parsers was originally developed for Java. Please be aware that there is no standard SAX2 API for C++, and that use of the Xerces-C++ SAX2 API does not guarantee client code compatibility with other C++ XML parsers.

Das folgende Beispiel bringt eine Schablone, mit der man XML-Dateien lesen kann. Mit Hilfe einer XMLReaderFactory legt man einen SAX2XMLReader an. Parallel dazu legt man einen selbstgeschriebenen Handler MySAX2Handler an. Letzterer ist eine Unterklasse eines DefaultHandlers den Xerces zur Verfügung stellt. Diesen Handler macht man dem SAX2XMLReader mit der Methode setContentHandler bekannt. Beim Parsen der dem SAX2XMLReader übergebenen XML-Datei werden dann die entsprechenden Methoden des Handlers aufgerufen und man kann diese Methoden dazu verwenden, die Daten aus der XML-Datei zu extrahieren.


Einen eigenen Handler entwerfen

Für dieses Beispiel benötigt VisualStudio Zugriff auf das include-Verzeichnis in xerces-c-3.1.1-x86-windows-vc-8.0\include sowie auch Zugriff auf die Bibliotheken xerces-c-3.1.1-x86-windows-vc-8.0\lib und schließlich muß noch die Datei xerces-c_3_1.dll im Verzeichnis der exe-Datei liegen. Diese DLL findet man in xerces-c-3.1.1-x86-windows-vc-8.0\bin (siehe auch die Screenshots am Ende des Kapitels.


Die Headerdatei
/*

*/
#ifndef _MYSAX2HANDLER_
#define _MYSAX2HANDLER_

#include <iostream>
#include <xercesc/sax2/DefaultHandler.hpp>

using namespace std;
using namespace xercesc;

class MySAX2Handler : public DefaultHandler
{
public:
   /**
    * Receive notification of the start of an element.
    *
    * By default, do nothing.  Application writers may override this
    * method in a subclass to take specific actions at the start of
    * each element (such as allocating a new tree node or writing
    * output to a file).
    *
    * @param uri The URI of the associated namespace for this element
    * @param localname the local part of the element name
    * @param qname the QName of this element
    * @param attrs The specified or defaulted attributes.
    * @exception SAXException Any SAX exception, possibly
    *            wrapping another exception.
    */
    void startElement( const XMLCh* const uri,
                  const XMLCh* const localname,
                  const XMLCh* const qname,
                    const Attributes&  attrs );
   /**
    * Receive notification of the end of an element.
    *
    * By default, do nothing.  Application writers may override this
    * method in a subclass to take specific actions at the end of
    * each element (such as finalising a tree node or writing
    * output to a file).
    *
    * @param uri The URI of the associated namespace for this element
    * @param localname The local part of the element name
    * @param qname The QName of this element
    * @exception SAXException Any SAX exception, possibly wrapping another exception.
    */
   void endElement( const XMLCh* const uri,
                const XMLCh* const localname,
                const XMLCh* const qname );

   /**
    * Receive notification of character data inside an element.
    *
    * By default, do nothing.  Application writers may override this
    * method to take specific actions for each chunk of character data
    * (such as adding the data to a node or buffer, or printing it to
    * a file).
    *
    * @param chars The characters.
    * @param length The number of characters to use from the
    *               character array.
    * @exception SAXException Any SAX exception, possibly wrapping another exception.
    */
    void characters( const XMLCh* const chars,
                const XMLSize_t length );

   /**
    * Receive notification of a recoverable parser error.
    *
    * The default implementation does nothing.  Application writers
    * may override this method in a subclass to take specific actions
    * for each error, such as inserting the message in a log file or
    * printing it to the console.
    */
   void error(const SAXParseException& ex);

   /**
    * Report a fatal XML parsing error.
    *
    * The default implementation throws a SAXParseException.
    * Application writers may override this method in a subclass if
    * they need to take specific actions for each fatal error (such as
    * collecting all of the errors into a single report): in any case,
    * the application must stop all regular processing when this
    * method is invoked, since the document is no longer reliable, and
    * the parser may no longer report parsing events.
    */
    void fatalError(const SAXParseException& ex);
};

#endif  // _MYSAX2HANDLER_

Die Implementierung
/*
MySAX2Handler Implementation
*/
#include "MySAX2Handler.h"

void MySAX2Handler::startElement( const XMLCh* const uri,
                          const XMLCh* const localname,
                          const XMLCh* const qname,
                             const Attributes&  attrs )
{
}

void MySAX2Handler::endElement( const XMLCh* const uri,
                        const XMLCh* const localname,
                        const XMLCh* const qname )
{
}

void MySAX2Handler::characters( const XMLCh* const chars,
                        const XMLSize_t length )
{
}

void MySAX2Handler::error(const SAXParseException& ex)
{
    char* message = XMLString::transcode(ex.getMessage());
    cout << "Error " << message << " at line: " << ex.getLineNumber() << endl;
    XMLString::release(&message);
}

void MySAX2Handler::fatalError(const SAXParseException& ex)
{
    char* message = XMLString::transcode(ex.getMessage());
    cout << "Fatal Error: " << message << " at line: " << ex.getLineNumber() << endl;
    XMLString::release(&message);
}

Die main-Funktion
/*
siehe auch
http://xerces.apache.org/xerces-c/program-sax2-3.html

die notwendige DLL (xerces-c_3_1.dll) ist in
xerces-c-3.1.1-x86-windows-vc-8.0\bin
*/

#include "MySAX2Handler.h"
#include <xercesc/util/XMLString.hpp>
#include <xercesc/sax2/SAX2XMLReader.hpp>
#include <xercesc/sax2/XMLReaderFactory.hpp>

//#include <iostream> wird bereits in MySAX2Handler.h eingezogen

//using namespace std; wird bereits in MySAX2Handler.h eingeführt
using namespace xercesc;

int main(int argc, char* argv[])
{
   try
   {
      XMLPlatformUtils::Initialize();
   }
   catch(const XMLException& ex)
   {
      char* message = XMLString::transcode(ex.getMessage());
      cout << "Initialization Error :\n";
      cout << "Exception message is: \n" << message << endl;
      XMLString::release(&message);
      return 1;
   }

    char* xmlFile = "test.xml";
    SAX2XMLReader* xmlReader = XMLReaderFactory::createXMLReader();
    xmlReader->setFeature(XMLUni::fgSAX2CoreValidation, true);
    xmlReader->setFeature(XMLUni::fgSAX2CoreNameSpaces, true);   // optional

    DefaultHandler* mySAX2Handler = new MySAX2Handler();
    xmlReader->setContentHandler(mySAX2Handler);
    xmlReader->setErrorHandler(mySAX2Handler);

   try
   {
      xmlReader->parse(xmlFile);
   }
    catch (const XMLException& ex)
   {
      char* message = XMLString::transcode(ex.getMessage());
      cout << "Exception message is: \n" << message << endl;
      XMLString::release(&message);
      return 2;
    }
   catch (const SAXParseException& ex)
   {
      char* message = XMLString::transcode(ex.getMessage());
      cout << "Exception message is: \n" << message << endl;
      XMLString::release(&message);
      return 2;
   }
      catch(...)
   {
      cout << "Unexpected Exception \n" ;
        return 2;
   }

   delete xmlReader;
   delete mySAX2Handler;

   return 0;
}

Die Einstellungen für VisualStudio

Projekteinstellungen

Compilereinstellungen

Damit das Beispiel auch auf andere C++ Entwicklungsumgebungen übertragbar ist, empfiehlt es sich keine vorcompilierten Header zu verwenden.

xerces-sax-01.jpg

xerces-sax-02.jpg


Linkereinstellungen

Bekanntmachen der Bibliothek.

xerces-sax-03.jpg

xerces-sax-04.jpg


DLL-Datei zur exe-Datei legen

Die notwendige DLL (xerces-c_3_1.dll) ist in xerces-c-3.1.1-x86-windows-vc-8.0\bin und muß in dasselbe Verzeichnis gelegt werden, in der die von Visual Studio angelegte exe-Datei liegt (oder ins system32-Verzeichnis)

xerces-sax-05.jpg

Hier sieht man, in welchem Teil des Projektverzeichnisses die XML-Datei gesucht wird. Die Projektmappe heißt xerces und das Projekt xerces01.

xerces-sax-06.jpg

Valid XHTML 1.0 Strict top Back Next Up Home