To jest stara wersja strony!
Autor: Krzysztof Mioduszewski 2008/04/14 23:59
Xerces-C++ DOM jest częścią Xerces-C++ API zaprojektowanego do współpracy z plikami w formacie XML. API umożliwia parsowania, manipulowanie, walidowanie oraz generowanie poprawnych dokumentów.
Biblioteka DOM jest implementacją następujących rekomendacji W3C:
Oraz zawiera częściową implementację (opartą o W3C Working Draft 09 April 2002) :
Więcej informacji na stronie projektu http://xerces.apache.org/xerces-c/. Na stronie znajdują się źródła, oraz skompilowane wersje biblioteki na różne platformy. Kompletna instrukcja instalacji na różnych platformach znajduje się tutaj.
Nagłówki, które powinniśmy dołączyć w przypadku pisania typowych aplikacji korzystających z Xerces DOM znajdują się poniżej:
#include <xercesc/util/PlatformUtils.hpp> #include <xercesc/util/XMLString.hpp> #include <xercesc/dom/DOM.hpp> #include <xercesc/parsers/XercesDOMParser.hpp>
Xerces posiada własny typ znakowy XMLCh
, który jest używany zamiast char
i std::string
. Do konwersji pomiędzy typami char*
a XMLCh*
(w obie strony) używana jest funkcja XMLString::transcode()
. Pamięć zaalokowaną na łańcuchy należy zwalniać za pomocą funkcji XMLString::release()
.
Przed użyciem jakichkolwiek klas Xerces konieczne jest wywołanie metody XMLPlatformUtils::Initialize()
. Po zakończeniu korzystania z Xerces powinno się wywołać XMLPlatformUtils::Terminate()
. Poniżej znajduje się uproszczona struktura programu (warto zwrócić uwagę na uzycie transcode()
).
#include <xercesc/util/PlatformUtils.hpp> #include <xercesc/util/XMLString.hpp> #include <xercesc/dom/DOM.hpp> #include <xercesc/parsers/XercesDOMParser.hpp> // ... #include <iostream> int main() { try { //incjalizacja Xerces-C++ xercesc::XMLPlatformUtils::Initialize(); } catch (const xercesc::XMLException& e) { //konwersja z XMLCh* na char* char* msg = xercesc::XMLString::transcode(e.getMessage()) ; std::cerr << "Init Error: " << msg << std::endl; //zwolnienie pamieci xercesc::XMLString::release(&msg) ; return 1; } // Tutaj korzystamy z mozliwosci Xerces-C++ xercesc::XMLPlatformUtils::Terminate(); return 0; }
Jest to parser umożliwiający wczytanie do pamięci struktury pliku XML za pomocą metody parse()
. Po czym uzyskujemy dostęp do obiektu DOMDocument
, po którym możemy poruszać się wykorzystując zaimplementowane w zgodzie z rekomendacjami W3C metody.
Poniżej przykładowe fragmenty kodu dotyczącego inicjalizacji i korzystania z XercesDOMParser
.
xercesc::XercesDOMParser* parser = new xercesc::XercesDOMParser(); parser->setValidationScheme(xercesc::XercesDOMParser::Val_Auto); //uruchamia walidację, jeżeli dostępne jest DTD (wewnętrzne/zewnętrzne) parser->setDoNamespaces(true); char* xmlFile = "file.xml"; try { parser->parse(xmlFile); } catch( const xercesc::XMLException& e ){ //... } catch( const xercesc::DOMException& e ){ //... } catch (...) { //... } //sprawdzamy czy nie wystąpiły błędy podczas parsowania if(parser->getErrorCount()==0) { xercesc::DOMDocument* XMLdoc = parser->getDocument(); //... }
Dobrym pomysłem jest zastosowanie własnego ErrorHandler
do wykrywania błędów składniowych w trakcie parsowania i wyświetlania o nich informacji (typ, miejsce wystąpienia). Najprostszy sposób to zaimplementowanie metod z interfejsu HandlerBase
:
#include <xercesc/sax/HandlerBase.hpp> class myErrorHandler : xercesc::HandlerBase { void warning( const xercesc::SAXParseException& e ) { char *msg = xercesc::XMLString::transcode(e.getMessage()); std::cout << "warning: " << msg << " | line: " << e.getLineNumber() << std::endl; xercesc::XMLString::release(&msg); } void error( const xercesc::SAXParseException& e ) { // analogicznie jak wyżej } void fatalError( const xercesc::SAXParseException& e ) { // j.w. } void resetErrors() {} }; //... xercesc::XercesDOMParser* parser = new xercesc::XercesDOMParser(); parser->setValidationScheme(xercesc::XercesDOMParser::Val_Auto); parser->setDoNamespaces(true); xercesc::ErrorHandler* errHandler = (xercesc::ErrorHandler*) new myErrorHandler(); parser->setErrorHandler(errHandler);
Gdy dokument zostanie sparsowany bez żadnych błędów możemy swobodnie zacząć na nim pracować wykorzystując zawarte w rekomendacjach metody. Poniżej kod zawierający przykładowe operacje:
//... xercesc::DOMDocument* XMLdoc = parser->getDocument(); xercesc::DOMElement* root = XMLdoc->getDocumentElement(); //pobieramy nazwę elementu głównego char* rootName = XMLString::transcode(root->getLocalName()); if(root->hasAttributes()) { xercesc::DOMNamedNodeMap* attrMap = root->getAttributes(); //iterujemy sobie po atrybutach for( XMLSize_t i = 0 ; i < attrMap->getLength() ; ++i ) { DOMAttr* attr = dynamic_cast<DOMAttr*>(attrMap->item(ix)); //wykorzystujemy sobie atrybut attr->getName(); //tutaj mamy nazwe attr->getValue(); //wartosc //... } }