开发者

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

开发者 https://www.devze.com 2022-12-17 04:10 出处:网络
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

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->开发者_如何学GogetDocumentElement();
    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)


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


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.


The sample CreateDOMDocument that comes with Xerces shows you how to add nodes etc. to a DOM document. The code you have so far creates the document, so you need to adapt the code in the second sample to add nodes, attributes etc.

Also, note that when you say:

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

the getAttributes function returns a collection of attributes - you need to apply further Xerces functions to that collection to get the contained information.

Note that if you want to extract a subset of the data in in e XML file, it may be easier to use an event driven SAX parser (Xerces includes one of these) rather than building and walking a complete DOM document.


If you want to see an example of how to do that using Xerces-C++, check out this code:

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

I wrote it a long time ago as a university project. It's most likely based on an outdated version of Xerces-C++, but I don't think the API has changed too much to be a problem. It will at least give you an idea.


The following link is a good tutorial that show basics for how to read an XML file and parse it with XERCES.

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

When that is done, the XERCES API should be enough for further operations:

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

For writing (serialize) the document, user the class DOMWriter http://xerces.apache.org/xerces-c/apiDocs-2/classDOMWriter.html#a0ddcef5fed6b49e03e53334fedca4b2

0

精彩评论

暂无评论...
验证码 换一张
取 消