Expat XML-Parser und XInclude??
-
Hallo Leute,
habe ein Problem und würde mich sehr über eine Lösung freuen. Ich verwende in einem Programm den Expat-XML-Parser, um XML-Dateien einzulesen. Funktioniert auch einwandfrei. Doch jetzt hätte ich gerne, dass ich in einer XML-Datei eine andere inkludieren kann (per XInclude):
xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="foo.xml"/>
Kurz: Der Parser meldet weder einen Fehler, noch inkludiert er die angegebene Datei!
Weitere Frage: Der Parser läuft ja auf nem lokalen Programm (in C), kann er da überhaupt mit einem Namespace aus dem Internet was anfangen?
Ich wäre um jegliche Idee sehr dankbar,
bin gerade am Verzweifeln.
Ach: Hab es auch mit Entitys probiert. Hat auch nicht funktioniert...
Gruß,
Bär
-
Gibt es keine Dokumentation zu dem Parser?
-
Die gibt nicht viel her zu dem Thema, das ist es ja gerade...
http://www.xml.com/pub/a/1999/09/expat/reference.html
-
Dieser Thread wurde von Moderator/in rüdiger aus dem Forum ANSI C in das Forum Rund um die Programmierung verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
Expat kann iirc nur ganz normales XML ohne irgend welche Erweiterungen wie XInclude. Wenn du so was brauchst, solltest du dir lieber libxml2 oä anschauen.
-
Warum nicht Xerces benutzen?
-
Ok, ich versuche mich gerade an Xerces als Alternative. Ich hätte gerne eine Funktion, der ich den Dateinamen der zu parsenden Datei übergeben kann und die anschließend die Datei parst und ich die einzelnen Tags auslesen kann.
Das hier hab ich von der Xerces-Homepage:
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); char* xmlFile = "x1.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; } delete parser; delete errHandler; return 0; }
Problem:
- Das ist erstens die Main -> ich will eine eigene Funktion, nicht die Main.
- Die Funktion kann ich nicht aufrufen, da die Parameter argc und args unbekannt sind.
- Wie übergebe ich der Funktion den Dateinamen ohne den Parser funktionsunfähig zu machen?Bitte helft mir, ich bin nicht gerade eine Leuchte in den Dingen
Danke,
Bärchen
-
Habs jetzt soweit zusammengeklaut aus diversen (leider Java-)Quellen ausm Internet:
bool CExpatParser::openXerces(std::string fname) { try { XMLPlatformUtils::Initialize(); } catch (const XMLException& toCatch) { char* message = XMLString::transcode(toCatch.getMessage()); XMLString::release(&message); return 1; } parse(fname); } void CExpatParser::parse(std::string file) { XercesDOMParser* parser = new XercesDOMParser(); parser->setValidationScheme(XercesDOMParser::Val_Always); parser->setDoNamespaces(true); // optional; try { parser->parse(file); writeDoc(parser->getDocument()->getDocumentElement()); } catch (const XMLException& toCatch) { char* message = XMLString::transcode(toCatch.getMessage()); XMLString::release(&message); return -1; } catch (const DOMException& toCatch) { char* message = XMLString::transcode(toCatch.msg); XMLString::release(&message); return -1; } catch (...) { return -1; } delete parser; delete errHandler; return 0; } void CExpatParser::writeDoc(DOMNode* node) { short type = node.getNodeType(); switch (type) { case Node->ELEMENT_NODE: { String name = "<" + node->getNodeName(); NamedNodeMap attrs = node->getAttributes(); if (attrs != 0) { int length = attrs.getLength(); for (int i = 0; i < length; i++) { Node attr = attrs.item(i); name += " " + attr.getNodeName(); name += "=\"" + attr.getNodeValue() + "\""; } } name += ">"; NodeList children = node.getChildNodes(); if (children != null) { int length = children.getLength(); for (int i = 0; i < length; i++) writeDoc(children.item(i)); } break; } case Node->TEXT_NODE: { //Drehe Däumchen break; } } }
Problem: DOMNode gibts nicht! Wenn ich den namespace nutze (using namespace xercesc;), gibts massig Errors alá "Funktion memcpy nicht vorhanden".
Kann mir wenigstens einer sagen, ob ich auf dem richtigen Weg bin oder bin ich völlig falsch?
Danke für die Hilfe!
Bär
-
#include <string.h>
Sorry for Spam, aber ich schreib noch einmal den neusten Stand rein. Nicht dass wieder Antworten kommen wie "Hä?" oder "versuch dich doch erstmal selber dran!".Also im Header includiere ich folgende Dateien:
#include <map> #include <vector> #include <expat.h> #include <stdio.h> #include <stdexcept> #include <xercesc/dom/DOM.hpp> #include <xercesc/dom/DOMDocument.hpp> #include <xercesc/dom/DOMDocumentType.hpp> #include <xercesc/dom/DOMElement.hpp> #include <xercesc/dom/DOMImplementation.hpp> #include <xercesc/dom/DOMImplementationLS.hpp> #include <xercesc/dom/DOMNodeIterator.hpp> #include <xercesc/dom/DOMNodeList.hpp> #include <xercesc/dom/DOMText.hpp> #include <xercesc/parsers/XercesDOMParser.hpp> #include <xercesc/util/XMLUni.hpp>
In meiner cpp-Datei kommt dann der Parser-Code:
#include <iostream> #include <sstream> #include <stdexcept> #include <list> #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #include "touchxmlparser.h" using namespace xercesc; using namespace std; bool CExpatParser::openXerces(std::string fname) { if (parse(fname) == 0) { return 1; } else { return 0; } } int CExpatParser::parse(std::string file) { try { XMLPlatformUtils::Initialize(); } catch (const XMLException& toCatch) { char* message = XMLString::transcode(toCatch.getMessage()); XMLString::release(&message); return 0; } XercesDOMParser* parser = new XercesDOMParser(); parser->setValidationScheme(XercesDOMParser::Val_Always); parser->setDoNamespaces(true); // optional; try { parser->parse(file.c_str()); // no need to free this pointer - owned by the parent parser object xercesc_3_0::DOMDocument* xmlDoc = parser->getDocument(); // Get the top-level element: NAme is "root". No attributes for "root" DOMElement* elementRoot = xmlDoc->getDocumentElement(); if( !elementRoot ) throw(std::runtime_error( "empty XML document" )); // Parse XML file for tags of interest: "ApplicationSettings" // Look one level nested within "root". (child of root) DOMNodeList* children = elementRoot->getChildNodes(); const XMLSize_t nodeCount = children->getLength(); // For all nodes, children of "root" in the XML tree. for( XMLSize_t xx = 0; xx < nodeCount; ++xx ) { DOMNode* currentNode = children->item(xx); if( currentNode->getNodeType() && // true is not NULL currentNode->getNodeType() == DOMNode::ELEMENT_NODE ) // is element { // Found node which is an Element. Re-cast node as element DOMElement* currentElement = dynamic_cast< xercesc::DOMElement* >( currentNode ); if( XMLString::equals(currentElement->getTagName(), XMLString::transcode("Definition"))) { // Already tested node as type element and of name "ApplicationSettings". // Read attributes of element "ApplicationSettings". const XMLCh* xmlch_OptionA = currentElement->getAttribute(XMLString::transcode("Attribut")); std::string m_OptionA = XMLString::transcode(xmlch_OptionA); const XMLCh* xmlch_OptionB = currentElement->getAttribute(XMLString::transcode("Attribut2")); std::string m_OptionB = XMLString::transcode(xmlch_OptionB); break; // Data found. No need to look at other elements in tree. } } } } catch (const XMLException& toCatch) { char* message = XMLString::transcode(toCatch.getMessage()); XMLString::release(&message); return -1; } catch (const DOMException& toCatch) { char* message = XMLString::transcode(toCatch.msg); XMLString::release(&message); return -1; } catch (...) { return -1; } delete parser; return 0; }
Bitte nicht von der Klasse Expat irritieren lassen, die ist natürlich Überbleibsel, da ich den Expat-Parser durch den Xerces ersetzen möchte.
Beim Compilieren ergeben Header und CPP-Datei keinen Error, allerdings kommt im XMLBuffer.cpp der Fehler:
[C++ Fehler] XMLBuffer.hpp(127): E2268 Aufruf der undefinierten Funktion 'memcpy'
Was mach ich jetzt noch falsch???