2010-01-24 26 views
7

Estoy buscando un tutorial para cargar un archivo XML, leerlo, cambiarlo y finalmente guardarlo con C++. Estoy usando Linux Ubuntu e intenté usar Xerces. Con Google y mucho tiempo, sólo podía cargar un archivo XML:Xerces C++ - ¿Cargar, leer y guardar, alternativas?

#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; 
} 

¿Cómo se puede leer un manipular el archivo XML y finalmente guardarlo? ¿Hay bibliotecas alternativas? (Intenté tinyxml pero los archivos devuelven errores, cuando quiero compilarlo)

+0

Espero que uses el nuevo Xerces 3. * el antiguo 2.7/2.8 tiene fugas de memoria por todo el lugar –

Respuesta

1

Parece que LibXML ++ es el mejor para C++. En lo que respecta a las funciones, es muy completo, incluidas las conversiones XPath, charset (por Glibmm) y todo lo que cabría esperar en una biblioteca XML. Utiliza las API DOM y SAX tradicionales, que cuentan como pro o como contra dependiendo de a quién le pregunte. Un posible problema es que las dependencias de la biblioteca son extremadamente pesadas (debido al uso de Glibmm). Aún así, parece ser la única biblioteca XML decente para C++.

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

TinyXML no analiza XML de acuerdo con la especificación, por lo que recomiendo en contra de ella, a pesar de que funciona para documentos simples.

0

El ejemplo CreateDOMDocument de ejemplo que viene con Xerces le muestra cómo agregar nodos, etc. a un documento DOM. El código que tiene hasta ahora crea el documento, por lo que necesita para adaptar el código en la segunda muestra para agregar nodos, atributos, etc.

Además, tenga en cuenta que cuando se dice:

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

la función getAttributes devuelve una colección de atributos: necesita aplicar otras funciones de Xerces a esa colección para obtener la información contenida.

Tenga en cuenta que si desea extraer un subconjunto de datos en un archivo e XML, puede ser más fácil usar un analizador SAX controlado por eventos (Xerces incluye uno de estos) en lugar de construir y recorrer un documento DOM completo.

0

Si desea ver un ejemplo de cómo hacerlo usando Xerces-C++, echa un vistazo a este código:

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

lo escribí hace mucho tiempo como un proyecto universitario. Lo más probable es que se base en una versión obsoleta de Xerces-C++, pero no creo que la API haya cambiado demasiado como para ser un problema. Al menos te dará una idea.

2

Una muestra para guardar xerces DOMDocument. Cómo guardar un documento con el código de

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

Ver ejemplo 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(); 

Y un ejemplo de aplicación del filtro. Puedes encontrar esto en el ejemplo 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

Esto me ayudó porque xerces era No solté mi archivo porque no estaba descargando ni borrando XMLFormatTarget. – jacobsgriffith

0

El siguiente enlace es un buen tutorial que muestra los conceptos básicos de cómo leer un archivo XML y analizarlo con XERCES.

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

Una vez hecho esto, la API XERCES debería ser suficiente para otras operaciones:

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

para la escritura (serialización) el documento, el usuario de la clase DOMWriter http://xerces.apache.org/xerces-c/apiDocs-2/classDOMWriter.html#a0ddcef5fed6b49e03e53334fedca4b2

Cuestiones relacionadas