00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00036 #include "OW_config.h"
00037 #include "OW_XMLPullParser.hpp"
00038 #include "OW_Format.hpp"
00039 #include "OW_Assertion.hpp"
00040 #include "OW_XMLUnescape.hpp"
00041 #include "OW_XMLParseException.hpp"
00042 #include <algorithm> 
00043 
00044 namespace OW_NAMESPACE
00045 {
00046 
00048 XMLPullParser::~XMLPullParser()
00049 {
00050 }
00051 
00053 void
00054 XMLPullParser::prime()
00055 {
00056    if (!(m_good = m_parser.next(m_curTok)))
00057    {
00058       OW_THROWXML(XMLParseException::SEMANTIC_ERROR, "Empty XML");
00059    }
00060    if (m_curTok.type == XMLToken::XML_DECLARATION)
00061    {
00062       if (!(m_good = m_parser.next(m_curTok)))
00063       {
00064          OW_THROWXML(XMLParseException::SEMANTIC_ERROR, "Empty XML");
00065       }
00066       skipData();
00067    }
00068    if (m_curTok.type == XMLToken::DOCTYPE)
00069    {
00070       if (!(m_good = m_parser.next(m_curTok)))
00071       {
00072          OW_THROWXML(XMLParseException::SEMANTIC_ERROR, "Empty XML");
00073       }
00074       skipData();
00075    }
00076 }
00078 XMLPullParser::XMLPullParser(const String& str)
00079    : m_ptfs(new TempFileStream())
00080    , m_parser()
00081    , m_curTok()
00082    , m_good(true)
00083 {
00084    *m_ptfs << str;
00085    m_parser.setInput(*m_ptfs);
00086    prime();
00087 }
00089 XMLPullParser::XMLPullParser(std::istream& istr)
00090    : m_ptfs()
00091    , m_parser(istr)
00092    , m_curTok()
00093    , m_good(true)
00094 {
00095    prime();
00096 }
00098 XMLPullParser::XMLPullParser()
00099    : m_good(false)
00100 {
00101 }
00102 
00104 String
00105 XMLPullParser::getAttribute(const char* const attrId, bool throwIfError) const
00106 {
00107    OW_ASSERT(m_curTok.type == XMLToken::START_TAG);
00108    for (unsigned i = 0; i < m_curTok.attributeCount; i++)
00109    {
00110       const XMLToken::Attribute& attr = m_curTok.attributes[i];
00111       
00112       if (attr.name.equals(attrId))
00113       {
00114          return XMLUnescape(attr.value.c_str(), attr.value.length());
00115       }
00116    }
00117    if (throwIfError)
00118    {
00119       OW_THROWXML(XMLParseException::BAD_ATTRIBUTE_NAME,
00120                Format("Failed to find "
00121                   "attribute: %1 in node: %2", attrId, m_curTok.text).c_str() );
00122    }
00123    return String();
00124 }
00126 void
00127 XMLPullParser::mustGetChild()
00128 {
00129    if (!m_good)
00130    {
00131       m_good = false;
00132       OW_THROWXML(XMLParseException::SEMANTIC_ERROR,
00133          Format("XMLPullParser::mustGetChild() failed.  parser = %1",
00134             *this).c_str());
00135    }
00136    getChild();
00137    if (!m_good)
00138    {
00139       m_good = false;
00140       OW_THROWXML(XMLParseException::SEMANTIC_ERROR,
00141          Format("XMLPullParser::mustGetChild() failed.  parser = %1",
00142             *this).c_str());
00143    }
00144 }
00146 void
00147 XMLPullParser::getChild()
00148 {
00149    if (!m_good)
00150    {
00151       return;
00152    }
00153    for (;;)
00154    {
00155       nextToken();
00156       if (!m_good)
00157       {
00158          return;
00159       }
00160       switch (m_curTok.type)
00161       {
00162          case XMLToken::END_TAG: 
00163             m_good = false;
00164          case XMLToken::START_TAG: 
00165             return;
00166          default:
00167             break;
00168       }
00169    }
00170 }
00172 void
00173 XMLPullParser::getNextTag(bool throwIfError)
00174 {
00175    nextToken();
00176    skipData();
00177    if (!m_good && throwIfError)
00178    {
00179       OW_THROWXML(XMLParseException::SEMANTIC_ERROR,
00180          Format("XMLPullParser::getNext() failed.  parser = %1",
00181             *this).c_str());
00182    }
00183 }
00185 void
00186 XMLPullParser::getNext(bool throwIfError)
00187 {
00188    nextToken();
00189    if (!m_good && throwIfError)
00190    {
00191       OW_THROWXML(XMLParseException::SEMANTIC_ERROR,
00192          Format("XMLPullParser::getNext() failed.  parser = %1",
00193             *this).c_str());
00194    }
00195 }
00197 void
00198 XMLPullParser::mustGetEndTag()
00199 {
00200    skipData();
00201    if (m_curTok.type != XMLToken::END_TAG)
00202    {
00203       OW_THROWXML(XMLParseException::SEMANTIC_ERROR,
00204          Format("XMLPullParser::mustGetEndTag() failed.  parser = %1",
00205             *this).c_str());
00206    }
00207    getNext();
00208    skipData();
00209 }
00211 String
00212 XMLPullParser::getName() const
00213 {
00214    OW_ASSERT(m_curTok.type == XMLToken::START_TAG || m_curTok.type == XMLToken::END_TAG);
00215    return XMLUnescape(m_curTok.text.c_str(), m_curTok.text.length());
00216 }
00218 String
00219 XMLPullParser::getData() const
00220 {
00221    OW_ASSERT(m_curTok.type == XMLToken::CONTENT || m_curTok.type == XMLToken::CDATA);
00222    return XMLUnescape(m_curTok.text.c_str(), m_curTok.text.length());
00223 }
00225 bool
00226 XMLPullParser::isData() const
00227 {
00228    return m_curTok.type == XMLToken::CONTENT || m_curTok.type == XMLToken::CDATA;
00229 }
00231 void
00232 XMLPullParser::nextToken()
00233 {
00234    do
00235    {
00236       m_good = m_parser.next(m_curTok);
00237    } while (m_curTok.type == XMLToken::COMMENT && m_good);
00238 }
00240 void
00241 XMLPullParser::skipData()
00242 {
00243    while (isData() && m_good)
00244    {
00245       nextToken();
00246    }
00247 }
00249 std::ostream& operator<<(std::ostream& ostr, const XMLPullParser& p)
00250 {
00251    ostr << "m_good = " << p.m_good << '\n';
00252    switch (p.m_curTok.type)
00253    {
00254       case XMLToken::INVALID:
00255          ostr << "*INVALID*\n";
00256          break;
00257       case XMLToken::XML_DECLARATION:
00258          ostr << "<xml>\n";
00259          break;
00260       case XMLToken::START_TAG:
00261          ostr << '<' << p.m_curTok.text << ' ';
00262          for (unsigned int x = 0; x < p.m_curTok.attributeCount; ++x)
00263          {
00264             ostr << p.m_curTok.attributes[x].name << "=\"" <<
00265                p.m_curTok.attributes[x].value << "\" ";
00266          }
00267          ostr << ">\n";
00268          break;
00269       case XMLToken::END_TAG:
00270          ostr << "</" << p.m_curTok.text << ">\n";
00271          break;
00272       case XMLToken::COMMENT:
00273          ostr << "<--" << p.m_curTok.text << "-->\n";
00274          break;
00275       case XMLToken::CDATA:
00276          ostr << "<CDATA[[" << p.m_curTok.text << "]]>\n";
00277          break;
00278       case XMLToken::DOCTYPE:
00279          ostr << "<DOCTYPE>\n";
00280          break;
00281       case XMLToken::CONTENT:
00282          ostr << "CONTENT: " << p.m_curTok.text << '\n';
00283          break;
00284       default:
00285          ostr << "Unknown token type\n";
00286    }
00287    return ostr;
00288 }
00289 
00290 } 
00291