00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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
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
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
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
00318
00319
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
00396
00397
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
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
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
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 ();
00663 }
00664 unsigned int sp = depth++ << 2;
00665
00666
00667 if (elementStack.size () <= sp + 4)
00668 elementStack.resize (sp + 4 + RESIZE_BUFFER);
00669 elementStack[sp + 3] = name;
00670
00671
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)
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