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
精彩评论