XmlPullParser.cpp

Go to the documentation of this file.
00001 /* Copyright (c) 2005,2007 Vivek Krishna
00002  *  Based on kxml2 by Stefan Haustein, Oberhausen, Rhld., Germany
00003  *  Permission is hereby granted, free of charge, to any person obtaining a copy
00004  * of this software and associated documentation files (the "Software"), to deal
00005  * in the Software without restriction, including without limitation the rights
00006  * to use, copy, modify, merge, publish, distribute, sublicense, and/or
00007  * sell copies of the Software, and to permit persons to whom the Software is
00008  * furnished to do so, subject to the following conditions:
00009  *
00010  * The  above copyright notice and this permission notice shall be included in
00011  * all copies or substantial portions of the Software.
00012  *
00013  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00014  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00015  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00016  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00017  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00018  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
00019  * IN THE SOFTWARE. */
00020 
00021 #include "xmlpull/XmlPullParser.h"
00022 #include "xmlpull/XmlPullParserException.h"
00023 #include "xmlpull/XmlUtils.h"
00024 //
00025 #include <cstring>
00026 
00027 
00028 XmlPullParser::XmlPullParser (std::istream & is)
00029   :unexpected_eof ("Unexpected EOF"),
00030    illegal_type ("wrong Event Type"),
00031    nspStack (16),
00032    elementStack (16),
00033    attributes (16),
00034    reader (is)
00035 {
00036   initBuf ();
00037   commonInit ();
00038 }
00039 
00040 
00041 XmlPullParser::XmlPullParser (void)
00042   :unexpected_eof ("Unexpected EOF"),
00043    illegal_type ("wrong Event Type"),
00044    nspStack (16),
00045    elementStack (16),
00046    attributes (16),
00047    reader (std::cin)
00048 {
00049   initBuf ();
00050   commonInit ();
00051 }
00052 
00053 
00054 void
00055 XmlPullParser::initBuf ()
00056 {
00057   srcBuf = new char[8192];
00058   srcBuflength = 8192;
00059   txtBuf = new char[256];
00060   txtBufSize = 256;
00061   nspCounts = new int[8];
00062   nspSize = 8;
00063 }
00064 
00065 
00066 //does common initializations
00067 void
00068 XmlPullParser::commonInit ()
00069 {
00070   line = 1;
00071   column = 0;
00072   type = START_DOCUMENT;
00073   name = "";
00074   Ns = "";
00075   degenerated = false;
00076   attributeCount = -1;
00077   encoding = "";
00078   version = "";
00079   standalone = false;
00080   unresolved = false;
00081   LEGACY = 999;
00082   XML_DECL = 998;
00083   srcPos = 0;
00084   srcCount = 0;
00085   peekCount = 0;
00086   depth = 0;
00087   relaxed = false;
00088   skipNextTag=false;
00089   entityMap["apos"] = "'";
00090   entityMap["gt"] = ">";
00091   entityMap["lt"] = "<";
00092   entityMap["quot"] = "\"";
00093   entityMap["amp"] = "&";
00094   for (int i = 0; i < nspSize; i++)
00095     nspCounts[i] = 0;
00096 }
00097 
00098 
00099 XmlPullParser::~XmlPullParser (void)
00100 {
00101   delete [] srcBuf;
00102   delete [] txtBuf;
00103   delete [] nspCounts;
00104 }
00105 
00106 
00107 std::string
00108 XmlPullParser::state (int eventType)
00109 {
00110   switch (eventType)
00111     {
00112     case 0:
00113       return "START_DOCUMENT";
00114     case 1:
00115       return "END_DOCUMENT";
00116     case 2:
00117       return "START_TAG";
00118     case 3:
00119       return "END_TAG";
00120     case 4:
00121       return "TEXT";
00122     case 5:
00123       return "CDSECT";
00124     case 6:
00125       return "ENTITY_REF";
00126     case 7:
00127       return "IGNORABLE_WHITESPACE";
00128     case 8:
00129       return "PROCESSING_INSTRUCTION";
00130     case 9:
00131       return "COMMENT";
00132     case 10:
00133       return "DOCDECL";
00134     default:
00135       return "Illegal state";
00136       break;
00137     }
00138   return "";
00139 }
00140 
00141 
00142 bool XmlPullParser::isProp (std::string n1, bool prop, std::string n2)
00143 {
00144   if (n1.find ("http://xmlpull.org/v1/doc/") != 0)
00145     return false;
00146   if (prop)
00147     return (n1.substr (42) == n2);
00148   else
00149     return (n1.substr (40) == n2);
00150 }
00151 
00152 
00153 bool XmlPullParser::adjustNsp ()
00154 {
00155   bool
00156     any = false;
00157   for (int i = 0; i < attributeCount << 2; i += 4)
00158 
00159     {
00160       std::string
00161         attrName = attributes[i + 2];
00162       int
00163         cut = attrName.find (":");
00164       std::string
00165         prefx;
00166       // Creating a variable named 'prefix' generates a warning about hiding the member, so I changed it to 'prefx'. -KEC
00167       if (cut != -1)
00168 
00169         {
00170           prefx = attrName.substr (0, cut);
00171           attrName = attrName.substr (cut + 1);
00172         }
00173 
00174       else if (attrName == "xmlns")
00175 
00176         {
00177           prefx = attrName;
00178           attrName = "";
00179         }
00180 
00181       else
00182         continue;
00183       if (prefx != "xmlns")
00184         {
00185           any = true;
00186         }
00187       else
00188         {
00189           unsigned int j = (nspCounts[depth]++) << 1;
00190 
00191           //nspStack = ensureCapacity(nspStack, j + 2);
00192           if (nspStack.size () <= j + 2)
00193             nspStack.resize (j + 2 + RESIZE_BUFFER);
00194           nspStack[j] = attrName;
00195           nspStack[j + 1] = attributes[i + 3];
00196           if (!attrName.empty () && attributes[i + 3] == "")
00197             exception ("illegal empty namespace");
00198 
00199           //vivek,array copy??
00200           int to = ((--attributeCount) << 2) - i;
00201           for (int p = 1; p <= to; p++)
00202             attributes[i + p - 1] = attributes[i + 4 + p - 1];
00203           i -= 4;
00204         }
00205     }
00206   if (any)
00207 
00208     {
00209       for (int i = (attributeCount << 2) - 4; i >= 0; i -= 4)
00210 
00211         {
00212           std::string
00213             attrName = attributes[i + 2];
00214           int
00215             cut = attrName.find (":");
00216           if (cut == 0 && !relaxed)
00217             exception ("illegal attribute name: " + attrName);
00218 
00219           else if (cut != -1)
00220 
00221             {
00222               std::string
00223                 attrPrefix = attrName.substr (0, cut);
00224               attrName = attrName.substr (cut + 1);
00225               std::string
00226                 attrNs = getNamespace (attrPrefix);
00227               if (attrNs.empty () && !relaxed)
00228                 exception ("Undefined Prefix: " + attrPrefix + " in ");
00229               attributes[i] = attrNs;
00230               attributes[i + 1] = attrPrefix;
00231               attributes[i + 2] = attrName;
00232               if (!relaxed)
00233 
00234                 {
00235                   for (int j = (attributeCount << 2) - 4; j > i; j -= 4)
00236                     if (attrName == attributes[j + 2]
00237                         && attrNs == attributes[j])
00238                       exception ("Duplicate Attribute: {"
00239                                  + attrNs + "}" + attrName);
00240                 }
00241             }
00242         }
00243     }
00244   int cut = name.find (":");
00245   if (cut == 0 && !relaxed)
00246     exception ("illegal tag name: " + name);
00247 
00248   else if (cut != -1)
00249     {
00250       prefix = name.substr (0, cut);
00251       name = name.substr (cut + 1);
00252     }
00253   Ns = getNamespace (prefix);
00254   if (Ns.empty ())
00255 
00256     {
00257       if (!prefix.empty () && !relaxed)
00258         exception ("undefined prefix: " + prefix);
00259       Ns = NO_NAMESPACE;
00260     }
00261   return any;
00262 }
00263 
00264 
00265 void
00266 XmlPullParser::exception (std::string desc)
00267 {
00268   XmlPullParserException e (desc, state (type), line, column);
00269   throw e;
00270 }
00271 
00272 
00276 void
00277 XmlPullParser::nextImpl ()
00278 {
00279   if (type == END_TAG)
00280     depth--;
00281   while (true)
00282     {
00283       attributeCount = -1;
00284       if (degenerated)
00285 
00286         {
00287           degenerated = false;
00288           type = END_TAG;
00289           return;
00290         }
00291       prefix = "";
00292       name = "";
00293       Ns = "";
00294       text = "";
00295       type = peekType ();
00296       switch (type)
00297         {
00298         case ENTITY_REF:
00299           pushEntity ();
00300           return;
00301         case START_TAG:
00302           parseStartTag (false);
00303           return;
00304         case END_TAG:
00305           parseEndTag ();
00306           return;
00307         case END_DOCUMENT:
00308           return;
00309         case TEXT:
00310           pushText ('<', !token);
00311           if (depth == 0)
00312 
00313             {
00314               if (isWspace)
00315                 type = IGNORABLE_WHITESPACE;
00316 
00317               // make exception switchable for instances.chg... !!!!
00318               //      else
00319               //    exception ("text '"+getText ()+"' not allowed outside root element");
00320             }
00321           return;
00322         default:
00323           type = parseLegacy (token);
00324           if (type != XML_DECL)
00325             return;
00326         }
00327     }
00328 }
00329 
00330 
00331 int
00332 XmlPullParser::parseLegacy (bool bpush)
00333 {
00334   std::string req = "";
00335   int term;
00336   int result;
00337   int prev = 0;
00338   read ();                                      // <
00339   int c = read ();
00340   if (c == '?')
00341 
00342     {
00343       if ((peekbuf (0) == 'x' || peekbuf (0) == 'X')
00344           && (peekbuf (1) == 'm' || peekbuf (1) == 'M'))
00345 
00346         {
00347           if (bpush)
00348 
00349             {
00350               push (peekbuf (0));
00351               push (peekbuf (1));
00352             }
00353           read ();
00354           read ();
00355           if ((peekbuf (0) == 'l' || peekbuf (0) == 'L')
00356               && peekbuf (1) <= ' ')
00357 
00358             {
00359               if (line != 1 || column > 4)
00360                 exception ("PI must not start with xml");
00361               parseStartTag (true);
00362               if (attributeCount < 1 || "version" != attributes[2])
00363                 exception ("version expected");
00364               version = attributes[3];
00365               int pos = 1;
00366               if (pos < attributeCount && "encoding" == attributes[2 + 4])
00367 
00368                 {
00369                   encoding = attributes[3 + 4];
00370                   pos++;
00371                 }
00372               if (pos < attributeCount
00373                   && "standalone" == attributes[4 * pos + 2])
00374 
00375                 {
00376                   std::string st = attributes[3 + 4 * pos];
00377                   if ("yes" == st)
00378                     standalone = true;
00379 
00380                   else if ("no" == st)
00381                     standalone = false;
00382 
00383                   else
00384                     exception ("illegal standalone value: " + st);
00385                   pos++;
00386                 }
00387               if (pos != attributeCount)
00388                 exception ("illegal xmldecl");
00389               isWspace = true;
00390               txtPos = 0;
00391               return XML_DECL;
00392             }
00393         }
00394 
00395       /*            int c0 = read ();
00396                     int c1 = read ();
00397                     int */
00398       term = '?';
00399       result = PROCESSING_INSTRUCTION;
00400     }
00401 
00402   else if (c == '!')
00403 
00404     {
00405       if (peekbuf (0) == '-')
00406 
00407         {
00408           result = COMMENT;
00409           req = "--";
00410           term = '-';
00411         }
00412 
00413       else if (peekbuf (0) == '[')
00414 
00415         {
00416           result = CDSECT;
00417           req = "[CDATA[";
00418           term = ']';
00419           bpush = true;
00420         }
00421 
00422       else
00423 
00424         {
00425           result = DOCDECL;
00426           req = "DOCTYPE";
00427           term = -1;
00428         }
00429     }
00430 
00431   else
00432 
00433     {
00434       exception ("illegal: <" + c);
00435       return -1;
00436     }
00437   for (unsigned int i = 0; i < req.length (); i++)
00438     read (req.at (i));
00439   if (result == DOCDECL)
00440     parseDoctype (bpush);
00441 
00442   else
00443 
00444     {
00445       while (true)
00446 
00447         {
00448           c = read ();
00449           if (c == -1)
00450             exception (unexpected_eof);
00451           if (bpush)
00452             push (c);
00453           if ((term == '?' || c == term)
00454               && peekbuf (0) == term && peekbuf (1) == '>')
00455             break;
00456           prev = c;
00457         }
00458       if (term == '-' && prev == '-' && !relaxed)
00459         exception ("illegal comment delimiter: --->");
00460       read ();
00461       read ();
00462       if (bpush && term != '?')
00463         txtPos--;
00464     }
00465   return result;
00466 }
00467 
00468 
00470 void
00471 XmlPullParser::parseDoctype (bool bpush)
00472 {
00473   int nesting = 1;
00474   bool quoted = false;
00475 
00476   // read();
00477   while (true)
00478 
00479     {
00480       int i = read ();
00481       switch (i)
00482 
00483         {
00484         case -1:
00485           exception (unexpected_eof);
00486         case '\'':
00487           quoted = !quoted;
00488           break;
00489         case '<':
00490           if (!quoted)
00491             nesting++;
00492           break;
00493         case '>':
00494           if (!quoted)
00495 
00496             {
00497               if ((--nesting) == 0)
00498                 return;
00499             }
00500           break;
00501         }
00502       if (bpush)
00503         push (i);
00504     }
00505 }
00506 
00507 
00508 /* precondition: &lt;/ consumed */
00509 void
00510 XmlPullParser::parseEndTag ()
00511 {
00512   read ();                                      // '<'
00513   read ();                                      // '/'
00514   name = readName ();
00515   skip ();
00516   read ('>');
00517   int sp = (depth - 1) << 2;
00518   if (!relaxed)
00519 
00520     {
00521       if (depth == 0)
00522         exception ("element stack empty");
00523       if (name != elementStack[sp + 3])
00524         exception ("expected: " + elementStack[sp + 3]);
00525     }
00526 
00527   else if (depth == 0 || name != elementStack[sp + 3])
00528     return;
00529   Ns = elementStack[sp];
00530   prefix = elementStack[sp + 1];
00531   name = elementStack[sp + 2];
00532 }
00533 
00534 
00535 int
00536 XmlPullParser::peekType ()
00537 {
00538   switch (peekbuf (0))
00539 
00540     {
00541     case -1:
00542       return END_DOCUMENT;
00543     case '&':
00544       return ENTITY_REF;
00545     case '<':
00546       switch (peekbuf (1))
00547 
00548         {
00549         case '/':
00550           return END_TAG;
00551         case '?':
00552         case '!':
00553           return LEGACY;
00554         default:
00555           return START_TAG;
00556         }
00557     default:
00558       return TEXT;
00559     }
00560 }
00561 
00562 
00563 std::string XmlPullParser::get (int pos)
00564 {
00565   std::string
00566     tmp (txtBuf);
00567   return tmp.substr (pos, txtPos - pos);
00568 }
00569 
00570 
00571 void
00572 XmlPullParser::push (int c)
00573 {
00574   isWspace &= c <= ' ';
00575   if (txtPos >= txtBufSize - 1)
00576 
00577     {
00578       char *bigger = new char[txtBufSize = txtPos * 4 / 3 + 4];
00579       memcpy (bigger, txtBuf, txtPos);
00580       delete[] txtBuf;
00581       txtBuf = bigger;
00582     }
00583   txtBuf[txtPos++] = (char) c;
00584   txtBuf[txtPos] = 0;
00585 }
00586 
00587 
00589 void
00590 XmlPullParser::parseStartTag (bool xmldecl)
00591 {
00592   if (!xmldecl)
00593     read ();
00594   name = readName ();
00595   attributeCount = 0;
00596   while (true)
00597 
00598     {
00599       skip ();
00600       int c = peekbuf (0);
00601       if (xmldecl)
00602 
00603         {
00604           if (c == '?')
00605 
00606             {
00607               read ();
00608               read ('>');
00609               return;
00610             }
00611         }
00612 
00613       else
00614 
00615         {
00616           if (c == '/')
00617 
00618             {
00619               degenerated = true;
00620               read ();
00621               skip ();
00622               read ('>');
00623               break;
00624             }
00625           if (c == '>' && !xmldecl)
00626 
00627             {
00628               read ();
00629               break;
00630             }
00631         }
00632       if (c == -1)
00633         exception (unexpected_eof);
00634       std::string attrName = readName ();
00635       if (attrName.empty ())
00636         exception ("attr name expected");
00637       skip ();
00638       read ('=');
00639       skip ();
00640       int delimiter = read ();
00641       if (delimiter != '\'' && delimiter != '"')
00642 
00643         {
00644           if (!relaxed)
00645             exception ("<"
00646                        + name + ">: invalid delimiter: " + (char) delimiter);
00647           delimiter = ' ';
00648         }
00649       unsigned int i = (attributeCount++) << 2;
00650 
00651       //attributes = ensureCapacity(attributes, i + 4);
00652       if (attributes.size () <= i + 4)
00653         attributes.resize (i + 4 + RESIZE_BUFFER);
00654       attributes[i++] = "";
00655       attributes[i++] = "";
00656       attributes[i++] = attrName;
00657       int p = txtPos;
00658       pushText (delimiter, true);
00659       attributes[i] = get (p);
00660       txtPos = p;
00661       if (delimiter != ' ')
00662         read ();                              // skip endquote
00663     }
00664   unsigned  int sp = depth++ << 2;
00665 
00666   //elementStack = ensureCapacity(elementStack, sp + 4,elementStackSize);
00667   if (elementStack.size () <= sp + 4)
00668     elementStack.resize (sp + 4 + RESIZE_BUFFER);
00669   elementStack[sp + 3] = name;
00670 
00671   /*    vivek ,avoided the increment array logic..fix later*/
00672   if (depth >= nspSize)
00673 
00674     {
00675       int *bigger = new int[nspSize + 4];
00676       int i = 0;
00677       for (i = 0; i < nspSize; i++)
00678         bigger[i] = nspCounts[i];
00679       for (i = nspSize; i < nspSize + 4; i++)
00680         bigger[i] = 0;
00681       delete [] nspCounts;
00682       nspCounts = bigger;
00683       nspSize += 4;
00684     }
00685   nspCounts[depth] = nspCounts[depth - 1];
00686   for (int i = attributeCount - 1; i > 0; i--)
00687 
00688     {
00689       for (int j = 0; j < i; j++)
00690 
00691         {
00692           if (getAttributeName (i) == getAttributeName (j))
00693             exception ("Duplicate Attribute: " + getAttributeName (i));
00694         }
00695     }
00696   if (processNsp)
00697     adjustNsp ();
00698 
00699   else
00700     Ns = "";
00701   elementStack[sp] = Ns;
00702   elementStack[sp + 1] = prefix;
00703   elementStack[sp + 2] = name;
00704 }
00705 
00706 
00709 void
00710 XmlPullParser::pushEntity ()
00711 {
00712   read ();                                      // &
00713   int pos = txtPos;
00714   while (true)
00715 
00716     {
00717       int c = read ();
00718       if (c == ';')
00719         break;
00720       if (relaxed && (c == '<' || c == '&' || c <= ' '))
00721 
00722         {
00723           if (c != -1)
00724             push (c);
00725           return;
00726         }
00727       if (c == -1)
00728         exception (unexpected_eof);
00729       push (c);
00730     }
00731   std::string code = get (pos);
00732   txtPos = pos;
00733   if (token && type == ENTITY_REF)
00734     name = code;
00735   if (code[0] == '#')
00736 
00737     {
00738       int c = (code[1] == 'x' ? XmlUtils::parseInt (code.substr (2),16)
00739                : XmlUtils::parseInt (code.substr (1)));
00740       push (c);
00741       return;
00742     }
00743   std::string result = (std::string) entityMap[code];
00744   unresolved = result == "";
00745   if (unresolved)
00746 
00747     {
00748       if (!token)
00749         exception ("unresolved: &" + code + ";");
00750     }
00751 
00752   else
00753 
00754     {
00755       for (unsigned int i = 0; i < result.length (); i++)
00756         push (result.at (i));
00757     }
00758 }
00759 
00760 
00766 void
00767 XmlPullParser::pushText (int delimiter, bool resolveEntities)
00768 {
00769   int next = peekbuf (0);
00770   while (next != -1 && next != delimiter)       // covers eof, '<', '"'
00771     {
00772       if (delimiter == ' ')
00773         if (next <= ' ' || next == '>')
00774           break;
00775       if (next == '&')
00776 
00777         {
00778           if (!resolveEntities)
00779             break;
00780           pushEntity ();
00781         }
00782 
00783       else if (next == '\n' && type == START_TAG)
00784 
00785         {
00786           read ();
00787           push (' ');
00788         }
00789 
00790       else
00791         push (read ());
00792       next = peekbuf (0);
00793     }
00794 }
00795 
00796 
00797 void
00798 XmlPullParser::read (char c)
00799 {
00800   int a = read ();
00801   std::string sa (1, (char) a), sc (1, c);
00802   if (a != c)
00803     exception ("expected: '" + sc + "' actual: '" + sa + "'");
00804 }
00805 
00806 
00807 int
00808 XmlPullParser::read ()
00809 {
00810   int result;
00811   if (peekCount == 0)
00812     result = peekbuf (0);
00813 
00814   else
00815 
00816     {
00817       result = peek[0];
00818       peek[0] = peek[1];
00819     }
00820   peekCount--;
00821   column++;
00822   if (result == '\n')
00823 
00824     {
00825       line++;
00826       column = 1;
00827     }
00828   return result;
00829 }
00830 
00831 
00833 int
00834 XmlPullParser::peekbuf (int pos)
00835 {
00836   while (pos >= peekCount)
00837 
00838     {
00839       int nw;
00840       if (srcBuflength <= 1)
00841         nw = reader.get ();
00842 
00843       else if (srcPos < srcCount)
00844         nw = srcBuf[srcPos++];
00845 
00846       else
00847 
00848         {
00849           srcCount = reader.read (srcBuf, srcBuflength).gcount ();
00850           if (srcCount <= 0)
00851             nw = -1;
00852 
00853           else
00854             nw = srcBuf[0];
00855           srcPos = 1;
00856         }
00857       if (nw == '\r')
00858 
00859         {
00860           wasCR = true;
00861           peek[peekCount++] = '\n';
00862         }
00863 
00864       else
00865 
00866         {
00867           if (nw == '\n')
00868 
00869             {
00870               if (!wasCR)
00871                 peek[peekCount++] = '\n';
00872             }
00873 
00874           else
00875             peek[peekCount++] = nw;
00876           wasCR = false;
00877         }
00878     }
00879   return peek[pos];
00880 }
00881 
00882 
00883 std::string XmlPullParser::readName ()
00884 {
00885   int  pos = txtPos;
00886   int  c = peekbuf (0);
00887   if ((c < 'a' || c > 'z')
00888       && (c < 'A' || c > 'Z') && c != '_' && c != ':' && c < 0x0c0)
00889     exception ("name expected");
00890 
00891   do
00892 
00893     {
00894       push (read ());
00895       c = peekbuf (0);
00896     }
00897   while ((c >= 'a' && c <= 'z')
00898          || (c >= 'A' && c <= 'Z')
00899          || (c >= '0' && c <= '9')
00900          || c == '_' || c == '-' || c == ':' || c == '.' || c >= 0x0b7);
00901   std::string
00902     result = get (pos);
00903   txtPos = pos;
00904   return result;
00905 }
00906 
00907 
00908 void
00909 XmlPullParser::skip ()
00910 {
00911   while (true)
00912 
00913     {
00914       int c = peekbuf (0);
00915       if (c > ' ' || c == -1)
00916         break;
00917       read ();
00918     }
00919 }
00920 
00921 
00922 //--------------- public part starts here... ---------------
00923 bool XmlPullParser::getFeature (std::string feature)
00924 {
00925   if (FEATURE_PROCESS_NAMESPACES == feature)
00926     return processNsp;
00927 
00928   else if (isProp (feature, false, "relaxed"))
00929     return relaxed;
00930 
00931   else
00932     return false;
00933 }
00934 
00935 
00936 std::string XmlPullParser::getInputEncoding ()
00937 {
00938   return encoding;
00939 }
00940 
00941 
00942 void
00943 XmlPullParser::defineEntityReplacementText (std::string entity, std::string value)
00944 {
00945   if (entityMap.empty ())
00946     exception ("entity replacement text must be defined after setInput!");
00947   entityMap[entity] = value;
00948 }
00949 
00950 
00951 int
00952 XmlPullParser::getNamespaceCount (int d)
00953 {
00954   if (d > depth)
00955     exception ("IndexOutOfBoundsException");;
00956   return nspCounts[d];
00957 }
00958 
00959 
00960 std::string XmlPullParser::getNamespacePrefix (int pos)
00961 {
00962   return nspStack[pos << 1];
00963 }
00964 
00965 
00966 std::string XmlPullParser::getNamespaceUri (int pos)
00967 {
00968   return nspStack[(pos << 1) + 1];
00969 }
00970 
00971 
00972 std::string XmlPullParser::getNamespace (std::string prefx)
00973 {
00974   if ("xml" == prefx)
00975     return "http://www.w3.org/XML/1998/namespace";
00976   if ("xmlns" == prefx)
00977     return "http://www.w3.org/2000/xmlns/";
00978   for (int i = (getNamespaceCount (depth) << 1) - 2; i >= 0; i -= 2)
00979 
00980     {
00981       if (prefx.empty ())
00982 
00983         {
00984 
00985           //cout<<nspStack[i]<<nspStack[i+1]<<endl;
00986           if (nspStack[i].empty ())
00987             return nspStack[i + 1];
00988         }
00989 
00990       else if (prefx == nspStack[i])
00991         return nspStack[i + 1];
00992     }
00993   return "";
00994 }
00995 
00996 
00997 int
00998 XmlPullParser::getDepth ()
00999 {
01000     return depth;
01001 }
01002 
01003 
01004 std::string 
01005 XmlPullParser::getPositionDescription ()
01006 {
01007   std::ostringstream buf (std::ios::ate);  
01008   //vivek,replace 11 by the number of event types
01009   buf << (type < 11 ? state (type) : "Unknown Event");
01010   buf << " ";
01011   if (type == START_TAG || type == END_TAG)
01012 
01013     {
01014       if (degenerated)
01015         buf << "(empty) ";
01016       buf << "<";
01017       if (type == END_TAG)
01018         buf << "/";
01019       if (!prefix.empty ())
01020         buf << "{" << Ns << "}" << prefix << ":";
01021       buf << name;
01022       int
01023         cnt = attributeCount << 2;
01024       for (int i = 0; i < cnt; i += 4)
01025 
01026         {
01027           buf << " ";
01028           if (!attributes[i + 1].empty ())
01029             buf << "{" << attributes[i] << "}" << attributes[i + 1] << ":";
01030           buf << attributes[i + 2] << "='" << attributes[i + 3] << "'";
01031         }
01032       buf << ">";
01033     }
01034 
01035   else if (type == IGNORABLE_WHITESPACE);
01036 
01037   else if (type != TEXT)
01038     buf << getText ();
01039 
01040   else if (isWspace)
01041     buf << "(whitespace)";
01042 
01043   else
01044 
01045     {
01046       std::string
01047         txt = getText ();
01048       if (txt.length () > 16)
01049         txt = txt.substr (0, 16) + "...";
01050       buf << txt;
01051     }
01052   buf << " @" << line << ":" << column;
01053   return buf.str ();                            //replace buf with an ostream
01054 }
01055 
01056 
01057 bool XmlPullParser::isWhitespace ()
01058 {
01059   if (type != TEXT && type != IGNORABLE_WHITESPACE && type != CDSECT)
01060     exception (illegal_type);
01061   return isWspace;
01062 }
01063 
01064 
01065 std::string XmlPullParser::getText ()
01066 {
01067   return type < TEXT || (type == ENTITY_REF && unresolved) ? "" : get (0);
01068 }
01069 
01070 
01071 const char *
01072 XmlPullParser::getTextCharacters (int *poslen)
01073 {
01074   if (type >= TEXT)
01075 
01076     {
01077       if (type == ENTITY_REF)
01078 
01079         {
01080           poslen[0] = 0;
01081           poslen[1] = name.length ();
01082           return name.c_str ();                 //return name.toCharArray();
01083         }
01084       poslen[0] = 0;
01085       poslen[1] = txtPos;
01086       return txtBuf;
01087     }
01088   poslen[0] = -1;
01089   poslen[1] = -1;
01090   return 0;
01091 }
01092 
01093 
01094 bool XmlPullParser::isEmptyElementTag ()
01095 {
01096   if (type != START_TAG)
01097     exception (illegal_type);
01098   return degenerated;
01099 }
01100 
01101 
01102 std::string XmlPullParser::getAttributeNamespace (int index)
01103 {
01104   if (index >= attributeCount)
01105     exception ("IndexOutOfBoundsException()");
01106   return attributes[index << 2];
01107 }
01108 
01109 
01110 std::string XmlPullParser::getAttributeName (int index)
01111 {
01112   if (index >= attributeCount)
01113     exception ("IndexOutOfBoundsException()");
01114   return attributes[(index << 2) + 2];
01115 }
01116 
01117 
01118 std::string XmlPullParser::getAttributePrefix (int index)
01119 {
01120     if (index >= attributeCount)
01121         exception ("IndexOutOfBoundsException()");
01122     return attributes[(index << 2) + 1];
01123 }
01124 
01125 
01126 std::string XmlPullParser::getAttributeValue (int index)
01127 {
01128     if (index >= attributeCount)
01129         exception ("IndexOutOfBoundsException()");
01130     return attributes[(index << 2) + 3];
01131 }
01132 
01133 
01134 std::string XmlPullParser::getAttributeValue (std::string ns, std::string nam)
01135 {
01136     for (int i = (attributeCount << 2) - 4; i >= 0; i -= 4)
01137 
01138     {
01139         if (attributes[i + 2] == nam && (ns.empty () || attributes[i] == ns))
01140             return attributes[i + 3];
01141     }
01142     return "";
01143 }
01144 
01145 
01146 int
01147 XmlPullParser::next ()
01148 {
01149     txtPos = 0;
01150     isWspace = true;
01151     int minType = 9999;
01152     token = false;
01153 
01154     do
01155 
01156     {
01157         nextImpl ();
01158         if (type < minType)
01159             minType = type;
01160 
01161 //          if (curr <= TEXT) type = curr;
01162     }
01163     while (minType > CDSECT                       // ignorable
01164         || (minType >= TEXT && peekType () >= TEXT));
01165     type = minType;
01166     if (type > TEXT)
01167         type = TEXT;
01168     return type;
01169 }
01170 
01171 
01172 int
01173 XmlPullParser::nextToken ()
01174 {
01175     isWspace = true;
01176     txtPos = 0;
01177     token = true;
01178     nextImpl ();
01179     return type;
01180 }
01181 
01182 void
01183 XmlPullParser::prevTag()
01184 {
01185   skipNextTag=true;
01186 }
01187 
01188 //----------------------------------------------------------------------
01189 // utility methods to make XML parsing easier ...
01190 int
01191 XmlPullParser::nextTag ()
01192 {
01193   if(skipNextTag){
01194     skipNextTag = false;
01195     return type;
01196   }
01197    next ();
01198     if (type == TEXT && isWspace)
01199         next ();
01200     if (type != END_TAG && type != START_TAG && type != END_DOCUMENT)
01201         exception ("unexpected type");
01202     return type;
01203 }
01204 
01205 
01206 void
01207 XmlPullParser::require (int Type, std::string ns, std::string nam)
01208 {
01209     if (Type != type || (!ns.empty () && ns != getNamespace ())
01210         || (!nam.empty () && nam != getName ()))
01211         exception ("expected: " + state (Type) + " {" + ns + "}" + nam);
01212 }
01213 
01214 
01215 std::string XmlPullParser::nextText ()
01216 {
01217     if (type != START_TAG)
01218         exception ("precondition: START_TAG");
01219     next ();
01220     std::string
01221         result;
01222     if (type == TEXT)
01223 
01224     {
01225         result = getText ();
01226         next ();
01227     }
01228 
01229     else
01230         result = "";
01231     if (type != END_TAG)
01232         exception ("END_TAG expected");
01233     return result;
01234 }
01235 
01236 
01237 void
01238 XmlPullParser::setFeature (std::string feature, bool value)
01239 {
01240     if (FEATURE_PROCESS_NAMESPACES == feature)
01241         processNsp = value;
01242 
01243     else if (isProp (feature, false, "relaxed"))
01244         relaxed = value;
01245 
01246     else
01247         exception ("unsupported feature: " + feature);
01248 }
01249 
01250 /*
01251 void
01252 XmlPullParser::setProperty(std::string property,  std::string value)
01253 {
01254   if(isProp(property, true, "location"))
01255     {
01256       location = value;
01257     }
01258   else
01259   exception ("unsupported property: " + property);
01260 }
01261 */
01262 
01268 //      Implementation copied from Alek's mail... 
01269 
01270 void
01271 XmlPullParser::skipSubTree() {
01272   require(START_TAG, "", "");
01273   int level = 1;
01274   while (level > 0) {
01275     int eventType = next();
01276     if (eventType == END_TAG) {
01277       --level;
01278     }
01279     else if (eventType == START_TAG) {
01280       ++level;
01281     }
01282   }
01283 }
01284 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by  doxygen 1.6.2