src/xmlpull/XmlPullParser.cpp

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

Generated on Sat May 3 16:29:00 2008 for wsdlpull by  doxygen 1.4.6