Xerces C++ - Load, read and save, alternatives?

15,786

Solution 1

A Sample for Saving xerces DOMDocument. Saving a Document with

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

see code Example 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();

And a example for Filter implementation. You can find this in DOMPrint example.

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

Solution 2

LibXML++ appears to be the best one for C++. Feature-wise it is very complete, including XPath, charset conversions (by Glibmm) and everything that you'd expect in an XML library. It uses traditional DOM and SAX APIs, which counts as a pro or a con depending on whom you ask from. One possible issue is that the dependencies of the library are extremely heavy (due to the use of Glibmm). Still, it appears to be the only decent XML library for C++.

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

TinyXML does not parse XML according to the specification, so I would recommend against it, even though it works for simple documents.

Share:
15,786
Admin
Author by

Admin

Updated on June 14, 2022

Comments

  • Admin
    Admin about 2 years

    I'm searching for a tutorial to load a XML file, read it, change it and finally save it with C++. I'm using Linux Ubuntu and tried to use Xerces. With Google and much time, I could only load an XML File:

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

    How do I can read an manipulate the XML file and finally save it? Is there alternative libraries? (I tried tinyxml but the files returns errors, when I want to compile it)