- Main Page
- Namespaces
- Classes
- Files
- Related Pages

# /Users/fpy/titan-1-5-MBARI/Mers/Utils/Io/Xml/Stream/Libxml2/Libxml2StreamReader.cpp

    00001
    00002 //
    00003 // Copyright (c) 2004           Model-based Embedded and Robotic Systems Group
    00004 // All Rights Reserved          Massachusetts Institute of Technology
    00005 //
    00006 // This software is provided as is. Model-based Embedded and Robotic Systems
    00007 // (MERS) group does not assume any responsibility.
    00008 //
    00009 // Organization:        Model-based Embedded and Robotic Systems Group
    00010 //                                      Massachusetts Institute of Technology
    00011 //
    00013
    00014 #include "Libxml2StreamReader.h"
    00015 #include <Mers/Utils/Io/Xml/Stream/XmlStreamException.h>
    00016
    00017 #include <cassert>
    00018 #include <sstream>
    00019 #include <iostream>
    00020
    00021 using namespace Mers::Utils::Io::Xml::Stream::Libxml2;
    00022 using namespace Mers::Utils::Io::Xml::Stream;
    00023 using namespace std;
    00024
    00025 // The location object (currently does not provide any information)
    00026 class Libxml2TextReaderLocation : public XmlStreamLocation
    00027 {
    00028 private:
    00029   xmlTextReader* reader;
    00030   string emptyString;
    00031
    00032 public:
    00033   Libxml2TextReaderLocation(xmlTextReader* myReader)
    00034     : reader(myReader) {}
    00035
    00036   virtual int getCharacterOffset() {return -1;}
    00037
    00038   virtual int getColumnNumber() {return -1;}
    00039
    00040   virtual int getLineNumber() {return -1;}
    00041
    00042   virtual const string& getPublicId() {return emptyString;}
    00043
    00044   virtual const string& getSystemId() {return emptyString;}
    00045
    00046 };
    00047
    00048
    00049 //-----------------------------------------
    00050 // Constructor and destructor
    00051 //-----------------------------------------
    00052
    00053 Libxml2StreamReader::Libxml2StreamReader(const string& filename)
    00054   : reader(xmlReaderForFile(filename.c_str(), NULL, 0)),
    00055     readerResult(1),
    00056     emptyElementEnd(false),
    00057     location(new Libxml2TextReaderLocation(reader))
    00058 {
    00059 }
    00060
    00061 Libxml2StreamReader::~Libxml2StreamReader()
    00062 {
    00063   xmlFreeTextReader(reader);
    00064 }
    00065
    00066 //-----------------------------------------
    00067 // Helper conversion functions
    00068 //-----------------------------------------
    00069 inline const xmlChar* string2xmlstr(const string& str) {
    00070   return reinterpret_cast<const xmlChar*>(str.c_str());
    00071 }
    00072
    00073 inline string xmlstr2string(const xmlChar* xmlstr) {
    00074   assert(xmlstr != NULL);
    00075   return string(reinterpret_cast<const char*>(xmlstr));
    00076 }
    00077
    00078 //-----------------------------------------
    00079 // Get functions
    00080 //-----------------------------------------
    00081 int Libxml2StreamReader::getAttributeCount() const {
    00082   return xmlTextReaderAttributeCount(reader);
    00083 }
    00084
    00085 const string& Libxml2StreamReader::getAttributeValue(const string& name) const{
    00086   xmlChar* xmlstr = xmlTextReaderGetAttribute(reader, string2xmlstr(name));
    00087   if(xmlstr != NULL) {
    00088     attributeValue=xmlstr2string(xmlstr);
    00089     free(xmlstr);
    00090   } else attributeValue = "";
    00091   return attributeValue;
    00092 }
    00093
    00094 const string& Libxml2StreamReader::getAttributeValue(const string&namespaceURI,
    00095                                                      const string& localName)
    00096   const
    00097 {
    00098   xmlChar* xmlstr =
    00099     xmlTextReaderGetAttributeNs(reader,
    00100                                 string2xmlstr(localName),
    00101                                 string2xmlstr(namespaceURI));
    00102   if(xmlstr != NULL) {
    00103     attributeValue=xmlstr2string(xmlstr);
    00104     free(xmlstr);
    00105   } else attributeValue = "";
    00106   return attributeValue;
    00107 }
    00108
    00109 const string& Libxml2StreamReader::getLocalName() const {
    00110   const xmlChar* xmlstr = xmlTextReaderConstName(reader);
    00111   localName = (xmlstr != NULL) ? xmlstr2string(xmlstr) : "";
    00112   // this ^^^ should be optimized at some point, so that we don't construct
    00113   // the string several times.
    00114   return localName;
    00115 }
    00116
    00117 const XmlStreamLocation& Libxml2StreamReader::getLocation() const {
    00118   return *location;
    00119 }
    00120
    00121 const string& Libxml2StreamReader::getText() const {
    00122   const xmlChar* xmlstr = xmlTextReaderConstValue(reader);
    00123   text = (xmlstr != NULL) ? xmlstr2string(xmlstr) : "";
    00124   return text;
    00125 }
    00126
    00127
    00128
    00129 //-----------------------------------------
    00130 // Event type functions
    00131 //-----------------------------------------
    00132 XmlStreamReader::EventType Libxml2StreamReader::getEventType() const {
    00133   if (readerResult == -1) {
    00134     throw XmlStreamException("Invalid state of the reader when calling "
    00135                              "getEventType()");
    00136   }
    00137
    00138   if(emptyElementEnd) return END_ELEMENT;
    00139   else {
    00140     switch(xmlTextReaderNodeType(reader)) {
    00141     case 2  /*XmlNodeType.Attribute*/: return ATTRIBUTE;
    00142     case 4  /*XmlNodeType.CDATA*/: return CDATA;
    00143     case 8  /*XmlNodeType.Comment*/: return COMMENT;
    00144     case 1  /*XmlNodeType.Element*/: return START_ELEMENT;
    00145     case 15 /*XmlNodeType.EndElement*/: return END_ELEMENT;
    00146     case 7 /*XmlNodeType.ProcessingInstruction*/:return PROCESSING_INSTRUCTION;
    00147     case 13 /*XmlNodeType.Whitespace*/: return SPACE;
    00148     case 14 /*XmlNodeType.SignificantWhitespace*/: return SPACE;
    00149     case 3  /*XmlNodeType.Text*/: return CHARACTERS;
    00150     case 0  /*XmlNodeType.None*/:
    00151       // This implementation uses (probably) undocumented behavior of libxml2
    00152       if (readerResult==1) { // has more elements
    00153         return START_DOCUMENT;
    00154       } else {
    00155         return END_DOCUMENT;
    00156       }
    00157     default: {
    00158       ostringstream msgstream;
    00159       msgstream << "Event type " << xmlTextReaderNodeType(reader)
    00160                 << " not yet recognized";
    00161       throw XmlStreamException(msgstream.str());
    00162     }
    00163     }
    00164   }
    00165 }
    00166
    00167
    00168 //-----------------------------------------
    00169 // Stream navigation functions
    00170 //-----------------------------------------
    00171
    00172 bool Libxml2StreamReader::hasNext() const {
    00173   return readerResult==1;
    00174 }
    00175
    00176 XmlStreamReader::EventType Libxml2StreamReader::next() {
    00177   if(xmlTextReaderIsEmptyElement(reader) && !emptyElementEnd
    00178      && isStartElement()) {
    00179     emptyElementEnd = true;
    00180   } else {
    00181     emptyElementEnd = false;
    00182     checkHasNext();
    00183     readerResult = xmlTextReaderRead(reader);
    00184     if(readerResult == -1) {
    00185       throw XmlStreamException("Failed to parse.");
    00186       // we should probably do a little more: capture the text and location
    00187       // of the error and pass it to XmlStreamException()x.
    00188     }
    00189   }
    00190   return getEventType();
    00191 }
    00192
    00193
    00194 XmlStreamReader::EventType Libxml2StreamReader::nextSibling() {
    00195   if(getEventType() == END_ELEMENT) {
    00196     throw XmlStreamException("Current node is END_ELEMENT in nextSibling()");
    00197   }
    00198   checkHasNext();
    00199   readerResult = xmlTextReaderNext(reader);
    00200   if(readerResult == -1) {
    00201     throw XmlStreamException("Failed to parse.");
    00202     // we should probably do a little more: capture the text and location
    00203     // of the error and pass it to XmlStreamException()x.
    00204   }
    00205   return getEventType();
    00206 }