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
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
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
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
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
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
00273
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
00316
00317
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
00394
00395
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
00468 void
00469 XmlPullParser::parseDoctype (bool bpush)
00470 {
00471 int nesting = 1;
00472 bool quoted = false;
00473
00474
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
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
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
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 ();
00661 }
00662 unsigned int sp = depth++ << 2;
00663
00664
00665 if (elementStack.size () <= sp + 4)
00666 elementStack.resize (sp + 4 + RESIZE_BUFFER);
00667 elementStack[sp + 3] = name;
00668
00669
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
00706
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
00760
00761
00762
00763
00764 void
00765 XmlPullParser::pushText (int delimiter, bool resolveEntities)
00766 {
00767 int next = peekbuf (0);
00768 while (next != -1 && next != delimiter)
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
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
01003 XmlPullParser::getPositionDescription ()
01004 {
01005 std::ostringstream buf (std::ios::ate);
01006 //vivek,replace 11 by the number of event types
01007 buf << (type < 11 ? state (type) : "Unknown Event");
01008 buf << " ";
01009 if (type == START_TAG || type == END_TAG)
01010
01011 {
01012 if (degenerated)
01013 buf << "(empty) ";
01014 buf << "<";
01015 if (type == END_TAG)
01016 buf << "/";
01017 if (!prefix.empty ())
01018 buf << "{" << Ns << "}" << prefix << ":";
01019 buf << name;
01020 int
01021 cnt = attributeCount << 2;
01022 for (int i = 0; i < cnt; i += 4)
01023
01024 {
01025 buf << " ";
01026 if (!attributes[i + 1].empty ())
01027 buf << "{" << attributes[i] << "}" << attributes[i + 1] << ":";
01028 buf << attributes[i + 2] << "='" << attributes[i + 3] << "'";
01029 }
01030 buf << ">";
01031 }
01032
01033 else if (type == IGNORABLE_WHITESPACE);
01034
01035 else if (type != TEXT)
01036 buf << getText ();
01037
01038 else if (isWspace)
01039 buf << "(whitespace)";
01040
01041 else
01042
01043 {
01044 std::string
01045 txt = getText ();
01046 if (txt.length () > 16)
01047 txt = txt.substr (0, 16) + "...";
01048 buf << txt;
01049 }
01050 buf << " @" << line << ":" << column;
01051 return buf.str (); //replace buf with an ostream
01052 }
01053
01054
01055 bool XmlPullParser::isWhitespace ()
01056 {
01057 if (type != TEXT && type != IGNORABLE_WHITESPACE && type != CDSECT)
01058 exception (illegal_type);
01059 return isWspace;
01060 }
01061
01062
01063 std::string XmlPullParser::getText ()
01064 {
01065 return type < TEXT || (type == ENTITY_REF && unresolved) ? "" : get (0);
01066 }
01067
01068
01069 const char *
01070 XmlPullParser::getTextCharacters (int *poslen)
01071 {
01072 if (type >= TEXT)
01073
01074 {
01075 if (type == ENTITY_REF)
01076
01077 {
01078 poslen[0] = 0;
01079 poslen[1] = name.length ();
01080 return name.c_str (); //return name.toCharArray();
01081 }
01082 poslen[0] = 0;
01083 poslen[1] = txtPos;
01084 return txtBuf;
01085 }
01086 poslen[0] = -1;
01087 poslen[1] = -1;
01088 return 0;
01089 }
01090
01091
01092 bool XmlPullParser::isEmptyElementTag ()
01093 {
01094 if (type != START_TAG)
01095 exception (illegal_type);
01096 return degenerated;
01097 }
01098
01099
01100 std::string XmlPullParser::getAttributeNamespace (int index)
01101 {
01102 if (index >= attributeCount)
01103 exception ("IndexOutOfBoundsException()");
01104 return attributes[index << 2];
01105 }
01106
01107
01108 std::string XmlPullParser::getAttributeName (int index)
01109 {
01110 if (index >= attributeCount)
01111 exception ("IndexOutOfBoundsException()");
01112 return attributes[(index << 2) + 2];
01113 }
01114
01115
01116 std::string XmlPullParser::getAttributePrefix (int index)
01117 {
01118 if (index >= attributeCount)
01119 exception ("IndexOutOfBoundsException()");
01120 return attributes[(index << 2) + 1];
01121 }
01122
01123
01124 std::string XmlPullParser::getAttributeValue (int index)
01125 {
01126 if (index >= attributeCount)
01127 exception ("IndexOutOfBoundsException()");
01128 return attributes[(index << 2) + 3];
01129 }
01130
01131
01132 std::string XmlPullParser::getAttributeValue (std::string ns, std::string nam)
01133 {
01134 for (int i = (attributeCount << 2) - 4; i >= 0; i -= 4)
01135
01136 {
01137 if (attributes[i + 2] == nam && (ns.empty () || attributes[i] == ns))
01138 return attributes[i + 3];
01139 }
01140 return "";
01141 }
01142
01143
01144 int
01145 XmlPullParser::next ()
01146 {
01147 txtPos = 0;
01148 isWspace = true;
01149 int minType = 9999;
01150 token = false;
01151
01152 do
01153
01154 {
01155 nextImpl ();
01156 if (type < minType)
01157 minType = type;
01158
01159 // if (curr <= TEXT) type = curr;
01160 }
01161 while (minType > CDSECT // ignorable
01162 || (minType >= TEXT && peekType () >= TEXT));
01163 type = minType;
01164 if (type > TEXT)
01165 type = TEXT;
01166 return type;
01167 }
01168
01169
01170 int
01171 XmlPullParser::nextToken ()
01172 {
01173 isWspace = true;
01174 txtPos = 0;
01175 token = true;
01176 nextImpl ();
01177 return type;
01178 }
01179
01180 void
01181 XmlPullParser::prevTag()
01182 {
01183 skipNextTag=true;
01184 }
01185
01186 //----------------------------------------------------------------------
01187 // utility methods to make XML parsing easier ...
01188 int
01189 XmlPullParser::nextTag ()
01190 {
01191 if(skipNextTag){
01192 skipNextTag = false;
01193 return type;
01194 }
01195 next ();
01196 if (type == TEXT && isWspace)
01197 next ();
01198 if (type != END_TAG && type != START_TAG && type != END_DOCUMENT)
01199 exception ("unexpected type");
01200 return type;
01201 }
01202
01203
01204 void
01205 XmlPullParser::require (int Type, std::string ns, std::string nam)
01206 {
01207 if (Type != type || (!ns.empty () && ns != getNamespace ())
01208 || (!nam.empty () && nam != getName ()))
01209 exception ("expected: " + state (Type) + " {" + ns + "}" + nam);
01210 }
01211
01212
01213 std::string XmlPullParser::nextText ()
01214 {
01215 if (type != START_TAG)
01216 exception ("precondition: START_TAG");
01217 next ();
01218 std::string
01219 result;
01220 if (type == TEXT)
01221
01222 {
01223 result = getText ();
01224 next ();
01225 }
01226
01227 else
01228 result = "";
01229 if (type != END_TAG)
01230 exception ("END_TAG expected");
01231 return result;
01232 }
01233
01234
01235 void
01236 XmlPullParser::setFeature (std::string feature, bool value)
01237 {
01238 if (FEATURE_PROCESS_NAMESPACES == feature)
01239 processNsp = value;
01240
01241 else if (isProp (feature, false, "relaxed"))
01242 relaxed = value;
01243
01244 else
01245 exception ("unsupported feature: " + feature);
01246 }
01247
01248 /*
01249 void
01250 XmlPullParser::setProperty(std::string property, std::string value)
01251 {
01252 if(isProp(property, true, "location"))
01253 {
01254 location = value;
01255 }
01256 else
01257 exception ("unsupported property: " + property);
01258 }
01259 */
01260
01261
01262
01263
01264
01265
01266 // Implementation copied from Alek's mail...
01267
01268 void
01269 XmlPullParser::skipSubTree() {
01270 require(START_TAG, "", "");
01271 int level = 1;
01272 while (level > 0) {
01273 int eventType = next();
01274 if (eventType == END_TAG) {
01275 --level;
01276 }
01277 else if (eventType == START_TAG) {
01278 ++level;
01279 }
01280 }
01281 }
01282