2010-01-24 15 views
7

Sto cercando un tutorial per caricare un file XML, leggerlo, cambiarlo e infine salvarlo con C++. Sto usando Linux Ubuntu e ho provato a usare Xerces. Con Google e molto tempo, ho potuto caricare solo un file XML:Xerces C++ - Carica, leggi e salva, alternative?

#include <xercesc/parsers/XercesDOMParser.hpp> 
#include <xercesc/dom/DOM.hpp> 
#include <xercesc/sax/HandlerBase.hpp> 
#include <xercesc/util/XMLString.hpp> 
#include <xercesc/util/PlatformUtils.hpp> 

#include <iostream> 

using namespace std; 
using namespace xercesc; 

int main (int argc, char* args[]) { 

    try { 
     XMLPlatformUtils::Initialize(); 
    } 
    catch (const XMLException& toCatch) { 
     char* message = XMLString::transcode(toCatch.getMessage()); 
     cout << "Error during initialization! :\n" 
      << message << "\n"; 
     XMLString::release(&message); 
     return 1; 
    } 

    XercesDOMParser* parser = new XercesDOMParser(); 
    parser->setValidationScheme(XercesDOMParser::Val_Always); 
    parser->setDoNamespaces(true); // optional 

    ErrorHandler* errHandler = (ErrorHandler*) new HandlerBase(); 
    parser->setErrorHandler(errHandler); 

    const char* xmlFile = "demo.xml"; 

    try { 
     parser->parse(xmlFile); 
    } 
    catch (const XMLException& toCatch) { 
     char* message = XMLString::transcode(toCatch.getMessage()); 
     cout << "Exception message is: \n" 
      << message << "\n"; 
     XMLString::release(&message); 
     return -1; 
    } 
    catch (const DOMException& toCatch) { 
     char* message = XMLString::transcode(toCatch.msg); 
     cout << "Exception message is: \n" 
      << message << "\n"; 
     XMLString::release(&message); 
     return -1; 
    } 
    catch (...) { 
     cout << "Unexpected Exception \n" ; 
     return -1; 
    } 

    DOMNode* docRootNode; 
// DOMNode* aNode; 
    DOMDocument* doc; 
    doc = parser->getDocument(); 
    docRootNode = doc->getDocumentElement(); 
    cout << docRootNode->getAttributes() << endl; //returns Hex 



    delete parser; 
    delete errHandler; 
    return 0; 
} 

Come si può leggere una manipolare i file XML e infine salvarlo? Esistono librerie alternative? (Ho provato tinyxml ma i file restituiscono errori, quando voglio compilarlo)

+0

Spero che tu usi il nuovo Xerces 3. * il vecchio 2.7/2.8 sta avendo perdite di memoria dappertutto –

risposta

1

LibXML ++ sembra essere il migliore per C++. In termini di funzionalità è molto completo, compreso XPath, le conversioni di charset (di Glibmm) e tutto ciò che ci si aspetterebbe da una libreria XML. Utilizza le tradizionali API DOM e SAX, che conta come un professionista o un truffatore a seconda di chi chiedi. Un possibile problema è che le dipendenze della libreria sono estremamente pesanti (a causa dell'uso di Glibmm). Tuttavia, sembra essere l'unica libreria XML decente per C++.

http://libxmlplusplus.sourceforge.net/docs/manual/html/index.html

TinyXML non analizza XML in base alla specifica, quindi consiglio contro di essa, anche se funziona per i documenti semplici.

0

L'esempio CreateDOMDocument fornito con Xerces mostra come aggiungere nodi ecc. A un documento DOM. Il codice si ha finora crea il documento, quindi è necessario adattare il codice nel secondo campione di aggiungere nodi, attributi ecc

Si noti inoltre che quando si dice:

cout << docRootNode->getAttributes() << endl; 

la funzione getAttributes restituisce una raccolta di attributi - è necessario applicare ulteriori funzioni Xerces a quella raccolta per ottenere le informazioni contenute.

Si noti che se si desidera estrarre un sottoinsieme di dati in un file XML, potrebbe essere più semplice utilizzare un parser SAX basato su eventi (Xerces include uno di questi) anziché costruire e camminare un documento DOM completo.

0

Se volete vedere un esempio di come farlo utilizzando Xerces-C++, controlla questo codice:

http://libprf1.tigris.org/files/documents/1338/13256/libprf1-0.1R3.tar.gz

ho scritto molto tempo fa come progetto universitario. Molto probabilmente si basa su una versione obsoleta di Xerces-C++, ma non credo che l'API sia cambiata troppo per essere un problema. Almeno ti darà un'idea.

2

Un esempio per il salvataggio di xerces DOMDocument. Salvataggio di un documento con il codice

DOMLSSerializer::write(const DOMNode* nodeToWrite, DOMLSOutput* const destination) 

vedi esempio http://xerces.apache.org/xerces-c/domprint-2.html

DOMLSSerializer * theSerializer = impl->createLSSerializer(); 
    DOMPrintFilter *myFilter = new DOMPrintFilter(DOMNodeFilter::SHOW_ELEMENT | 
             DOMNodeFilter::SHOW_ATTRIBUTE | 
             DOMNodeFilter::SHOW_DOCUMENT_TYPE); 
    theSerializer->setFilter(myFilter); 

    DOMLSOutput  *theOutputDesc = ((DOMImplementationLS*)impl)->createLSOutput(); 
    XMLFormatTarget *myFormTarget = new LocalFileFormatTarget(XMLString::transcode("C:\\target.xml")); 
    theOutputDesc->setByteStream(myFormTarget); 
    theOutputDesc->setEncoding(XMLString::transcode("ISO-8859-1")); 

    theSerializer->getDomConfig()->setParameter(XMLUni::fgDOMXMLDeclaration, true); 

    theSerializer->getDomConfig()->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true); 
    theSerializer->write(doc, theOutputDesc); 

    myFormTarget->flush(); 

    delete myFormTarget; 

    theOutputDesc->release(); 
    theSerializer->release(); 

E un esempio di attuazione del filtro. Puoi trovarlo nell'esempio di DOMPrint.

class DOMPrintFilter : public DOMLSSerializerFilter { 
public: 

    DOMPrintFilter(ShowType whatToShow = DOMNodeFilter::SHOW_ALL); 
    ~DOMPrintFilter(){}; 

    virtual FilterAction acceptNode(const DOMNode*) const; 
    virtual ShowType getWhatToShow() const {return fWhatToShow;}; 

private: 
    // unimplemented copy ctor and assignement operator 
    DOMPrintFilter(const DOMPrintFilter&); 
    DOMPrintFilter & operator = (const DOMPrintFilter&); 

    ShowType fWhatToShow; 
}; 
#include "DOMPrintFilter.hpp" 
#include <xercesc/util/XMLUniDefs.hpp> 
#include <xercesc/util/XMLString.hpp> 

static const XMLCh element_person[]= 
{ 
chLatin_p, chLatin_e, chLatin_r, chLatin_s, chLatin_o, chLatin_n, chNull 
}; 

static const XMLCh element_link[]= 
{ 
chLatin_l, chLatin_i, chLatin_n, chLatin_k, chNull 
}; 

DOMPrintFilter::DOMPrintFilter(ShowType whatToShow) 
:fWhatToShow(whatToShow) 
{} 

DOMNodeFilter::FilterAction DOMPrintFilter:: 
acceptNode(const DOMNode* node) const 
{ 
// 
// The DOMLSSerializer shall call getWhatToShow() before calling 
// acceptNode(), to show nodes which are supposed to be 
// shown to this filter. 
// 
// REVISIT: In case the DOMLSSerializer does not follow the protocol, 
//   Shall the filter honour, or NOT, what it claims 
//   it is interested in ? 
// 
// The DOMLS specs does not specify that acceptNode() shall do 
// this way, or not, so it is up the implementation, 
// to skip the code below for the sake of performance ... 
// 
if ((getWhatToShow() & (1 << (node->getNodeType() - 1))) == 0) 
    return DOMNodeFilter::FILTER_ACCEPT; 

switch (node->getNodeType()) 
{ 
case DOMNode::ELEMENT_NODE: 
    { 
     // for element whose name is "person", skip it 
     if (XMLString::compareString(node->getNodeName(),   element_person)==0) 
      return DOMNodeFilter::FILTER_SKIP; 
     // for element whose name is "line", reject it 
     if (XMLString::compareString(node->getNodeName(), element_link)==0) 
      return DOMNodeFilter::FILTER_REJECT; 
     // for rest, accept it 
     return DOMNodeFilter::FILTER_ACCEPT; 

     break; 
    } 
case DOMNode::COMMENT_NODE: 
    { 
     // the WhatToShow will make this no effect 
     return DOMNodeFilter::FILTER_REJECT; 
     break; 
    } 
case DOMNode::TEXT_NODE: 
    { 
     // the WhatToShow will make this no effect 
     return DOMNodeFilter::FILTER_REJECT; 
     break; 
    } 
case DOMNode::DOCUMENT_TYPE_NODE: 
    { 
     // even we say we are going to process document type, 
     // we are not able be to see this node since 
     // DOMLSSerializerImpl (a XercesC's default implementation 
     // of DOMLSSerializer) will not pass DocumentType node to 
     // this filter. 
     // 
     return DOMNodeFilter::FILTER_REJECT; // no effect 
     break; 
    } 
case DOMNode::DOCUMENT_NODE: 
    { 
     // same as DOCUMENT_NODE 
     return DOMNodeFilter::FILTER_REJECT; // no effect 
     break; 
    } 
default : 
    { 
     return DOMNodeFilter::FILTER_ACCEPT; 
     break; 
    } 
} 

return DOMNodeFilter::FILTER_ACCEPT; 
} 
+0

Questo mi ha aiutato perché xerces era non rilasciare il mio file perché non stavo scaricando né cancellando XMLFormatTarget. – jacobsgriffith

0

Il seguente collegamento è un buon tutorial che mostra le nozioni di base su come leggere un file XML e analizzarlo con XERCES.

http://www.yolinux.com/TUTORIALS/XML-Xerces-C.html

Quando questo è fatto, l'API Xerces dovrebbe essere sufficiente per ulteriori operazioni:

http://xerces.apache.org/xerces-c/apiDocs-2/classes.html

per la scrittura (serializzare) il documento, l'utente della classe DOMWriter http://xerces.apache.org/xerces-c/apiDocs-2/classDOMWriter.html#a0ddcef5fed6b49e03e53334fedca4b2