00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "TXMLEngine.h"
00023
00024 #include "Riostream.h"
00025 #include "TString.h"
00026 #include <stdlib.h>
00027 #include <string.h>
00028
00029 ClassImp(TXMLEngine);
00030
00031 struct SXmlAttr_t {
00032 SXmlAttr_t *fNext;
00033
00034
00035 static inline char* Name(void* arg) { return (char*)arg + sizeof(SXmlAttr_t); }
00036 };
00037
00038 enum EXmlNodeType {
00039 kXML_NODE = 1,
00040 kXML_COMMENT = 2,
00041 kXML_PI_NODE = 3,
00042 kXML_RAWLINE = 4
00043 };
00044
00045 struct SXmlNode_t {
00046 EXmlNodeType fType;
00047 SXmlAttr_t *fAttr;
00048 SXmlAttr_t *fNs;
00049 SXmlNode_t *fNext;
00050 SXmlNode_t *fChild;
00051 SXmlNode_t *fLastChild;
00052 SXmlNode_t *fParent;
00053
00054
00055 static inline char* Name(void* arg) { return (char*)arg + sizeof(SXmlNode_t); }
00056 };
00057
00058 #define XML_NODE_NAME(arg) (
00059
00060
00061 struct SXmlDoc_t {
00062 SXmlNode_t *fRootNode;
00063 char *fDtdName;
00064 char *fDtdRoot;
00065 };
00066
00067 class TXMLOutputStream {
00068 protected:
00069
00070 std::ostream *fOut;
00071 TString *fOutStr;
00072 char *fBuf;
00073 char *fCurrent;
00074 char *fMaxAddr;
00075 char *fLimitAddr;
00076
00077 public:
00078 TXMLOutputStream(const char* filename, Int_t bufsize = 20000)
00079 {
00080 fOut = new std::ofstream(filename);
00081 fOutStr = 0;
00082 Init(bufsize);
00083 }
00084
00085 TXMLOutputStream(TString* outstr, Int_t bufsize = 20000)
00086 {
00087 fOut = 0;
00088 fOutStr = outstr;
00089 Init(bufsize);
00090 }
00091
00092 void Init(Int_t bufsize)
00093 {
00094 fBuf = (char*) malloc(bufsize);
00095 fCurrent = fBuf;
00096 fMaxAddr = fBuf + bufsize;
00097 fLimitAddr = fBuf + int(bufsize*0.75);
00098 }
00099
00100 virtual ~TXMLOutputStream()
00101 {
00102 if (fCurrent!=fBuf) OutputCurrent();
00103 delete fOut;
00104 }
00105
00106 void OutputCurrent()
00107 {
00108 if (fCurrent!=fBuf) {
00109 if (fOut!=0)
00110 fOut->write(fBuf, fCurrent-fBuf);
00111 else if (fOutStr!=0)
00112 fOutStr->Append(fBuf, fCurrent-fBuf);
00113 }
00114 fCurrent = fBuf;
00115 }
00116
00117 void OutputChar(char symb)
00118 {
00119 if (fOut!=0) fOut->put(symb); else
00120 if (fOutStr!=0) fOutStr->Append(symb);
00121 }
00122
00123 void Write(const char* str)
00124 {
00125 int len = strlen(str);
00126 if (fCurrent+len>=fMaxAddr) {
00127 OutputCurrent();
00128 fOut->write(str,len);
00129 } else {
00130 while (*str)
00131 *fCurrent++ = *str++;
00132 if (fCurrent>fLimitAddr)
00133 OutputCurrent();
00134 }
00135 }
00136
00137 void Put(char symb, Int_t cnt=1)
00138 {
00139 if (fCurrent+cnt>=fMaxAddr)
00140 OutputCurrent();
00141 if (fCurrent+cnt>=fMaxAddr)
00142 for(int n=0;n<cnt;n++)
00143 OutputChar(symb);
00144 else {
00145 for(int n=0;n<cnt;n++)
00146 *fCurrent++ = symb;
00147 if (fCurrent>fLimitAddr)
00148 OutputCurrent();
00149 }
00150 }
00151 };
00152
00153 class TXMLInputStream {
00154 protected:
00155
00156 std::istream *fInp;
00157 const char *fInpStr;
00158 Int_t fInpStrLen;
00159
00160 char *fBuf;
00161 Int_t fBufSize;
00162
00163 char *fMaxAddr;
00164 char *fLimitAddr;
00165
00166 Int_t fTotalPos;
00167 Int_t fCurrentLine;
00168
00169 public:
00170
00171 char *fCurrent;
00172
00173 TXMLInputStream(bool isfilename, const char* filename, Int_t ibufsize)
00174 {
00175 if (isfilename) {
00176 fInp = new std::ifstream(filename);
00177 fInpStr = 0;
00178 fInpStrLen = 0;
00179 } else {
00180 fInp = 0;
00181 fInpStr = filename;
00182 fInpStrLen = filename==0 ? 0 : strlen(filename);
00183 }
00184
00185 fBufSize = ibufsize;
00186 fBuf = (char*) malloc(fBufSize);
00187
00188 fCurrent = 0;
00189 fMaxAddr = 0;
00190
00191 int len = DoRead(fBuf, fBufSize);
00192 fCurrent = fBuf;
00193 fMaxAddr = fBuf+len;
00194 fLimitAddr = fBuf + int(len*0.75);
00195
00196 fTotalPos = 0;
00197 fCurrentLine = 1;
00198 }
00199
00200 virtual ~TXMLInputStream()
00201 {
00202 delete fInp; fInp = 0;
00203 free(fBuf); fBuf = 0;
00204 }
00205
00206 inline Bool_t EndOfFile() { return (fInp!=0) ? fInp->eof() : (fInpStrLen<=0); }
00207
00208 inline Bool_t EndOfStream() { return EndOfFile() && (fCurrent>=fMaxAddr); }
00209
00210 int DoRead(char* buf, int maxsize)
00211 {
00212 if (EndOfFile()) return 0;
00213 if (fInp!=0) {
00214 fInp->get(buf, maxsize, 0);
00215 maxsize = strlen(buf);
00216 } else {
00217 if (maxsize>fInpStrLen) maxsize = fInpStrLen;
00218 strncpy(buf, fInpStr, maxsize);
00219 fInpStr+=maxsize;
00220 fInpStrLen-=maxsize;
00221 }
00222 return maxsize;
00223 }
00224
00225 Bool_t ExpandStream()
00226 {
00227 if (EndOfFile()) return kFALSE;
00228 fBufSize*=2;
00229 int curlength = fMaxAddr - fBuf;
00230 char* newbuf = (char*) realloc(fBuf, fBufSize);
00231 if (newbuf==0) return kFALSE;
00232
00233 fMaxAddr = newbuf + (fMaxAddr - fBuf);
00234 fCurrent = newbuf + (fCurrent - fBuf);
00235 fLimitAddr = newbuf + (fLimitAddr - fBuf);
00236 fBuf = newbuf;
00237
00238 int len = DoRead(fMaxAddr, fBufSize-curlength);
00239 if (len==0) return kFALSE;
00240 fMaxAddr += len;
00241 fLimitAddr += int(len*0.75);
00242 return kTRUE;
00243 }
00244
00245 Bool_t ShiftStream()
00246 {
00247 if (fCurrent<fLimitAddr) return kTRUE;
00248 if (EndOfFile()) return kTRUE;
00249 int rest_len = fMaxAddr - fCurrent;
00250 memmove(fBuf, fCurrent, rest_len);
00251 int read_len = DoRead(fBuf + rest_len, fBufSize - rest_len);
00252
00253 fCurrent = fBuf;
00254 fMaxAddr = fBuf + rest_len + read_len;
00255 fLimitAddr = fBuf + int((rest_len + read_len)*0.75);
00256 return kTRUE;
00257 }
00258
00259 Int_t TotalPos() { return fTotalPos; }
00260
00261 Int_t CurrentLine() { return fCurrentLine; }
00262
00263 Bool_t ShiftCurrent(Int_t sz = 1)
00264 {
00265 for(int n=0;n<sz;n++) {
00266 if (*fCurrent==10) fCurrentLine++;
00267 if (fCurrent>=fLimitAddr) {
00268 ShiftStream();
00269 if (fCurrent>=fMaxAddr) return kFALSE;
00270 }
00271 fCurrent++;
00272 }
00273 fTotalPos+=sz;
00274 return kTRUE;
00275 }
00276
00277 Bool_t SkipSpaces(Bool_t tillendl = kFALSE)
00278 {
00279 do {
00280 char symb = *fCurrent;
00281 if ((symb>26) && (symb!=' ')) return kTRUE;
00282
00283 if (!ShiftCurrent()) return kFALSE;
00284
00285 if (tillendl && (symb==10)) return kTRUE;
00286 } while (fCurrent<fMaxAddr);
00287 return kFALSE;
00288 }
00289
00290 Bool_t CheckFor(const char* str)
00291 {
00292
00293 int len = strlen(str);
00294 while (fCurrent+len>fMaxAddr)
00295 if (!ExpandStream()) return kFALSE;
00296 char* curr = fCurrent;
00297 while (*str != 0)
00298 if (*str++ != *curr++) return kFALSE;
00299 return ShiftCurrent(len);
00300 }
00301
00302 Int_t SearchFor(const char* str)
00303 {
00304
00305
00306 int len = strlen(str);
00307
00308 char* curr = fCurrent;
00309
00310 do {
00311 curr++;
00312 while (curr+len>fMaxAddr)
00313 if (!ExpandStream()) return -1;
00314 char* chk0 = curr;
00315 const char* chk = str;
00316 Bool_t find = kTRUE;
00317 while (*chk != 0)
00318 if (*chk++ != *chk0++) { find = kFALSE; break; }
00319
00320 if (find) return curr - fCurrent;
00321 } while (curr<fMaxAddr);
00322 return -1;
00323 }
00324
00325 Int_t LocateIdentifier()
00326 {
00327 char symb = *fCurrent;
00328 Bool_t ok = (((symb>='a') && (symb<='z')) ||
00329 ((symb>='A') && (symb<='Z')) ||
00330 (symb=='_'));
00331 if (!ok) return 0;
00332
00333 char* curr = fCurrent;
00334
00335 do {
00336 curr++;
00337 if (curr>=fMaxAddr)
00338 if (!ExpandStream()) return 0;
00339 symb = *curr;
00340 ok = ((symb>='a') && (symb<='z')) ||
00341 ((symb>='A') && (symb<='Z')) ||
00342 ((symb>='0') && (symb<='9')) ||
00343 (symb==':') || (symb=='_') || (symb=='-');
00344 if (!ok) return curr-fCurrent;
00345 } while (curr<fMaxAddr);
00346 return 0;
00347 }
00348
00349 Int_t LocateContent()
00350 {
00351 char* curr = fCurrent;
00352 while (curr<fMaxAddr) {
00353 char symb = *curr;
00354 if (symb=='<') return curr - fCurrent;
00355 curr++;
00356 if (curr>=fMaxAddr)
00357 if (!ExpandStream()) return -1;
00358 }
00359 return -1;
00360 }
00361
00362 Int_t LocateAttributeValue(char* start)
00363 {
00364 char* curr = start;
00365 if (curr>=fMaxAddr)
00366 if (!ExpandStream()) return 0;
00367 if (*curr!='=') return 0;
00368 curr++;
00369 if (curr>=fMaxAddr)
00370 if (!ExpandStream()) return 0;
00371 if (*curr!='"') return 0;
00372 do {
00373 curr++;
00374 if (curr>=fMaxAddr)
00375 if (!ExpandStream()) return 0;
00376 if (*curr=='"') return curr-start+1;
00377 } while (curr<fMaxAddr);
00378 return 0;
00379 }
00380 };
00381
00382
00383 TXMLEngine::TXMLEngine()
00384 {
00385
00386 fSkipComments = kFALSE;
00387 }
00388
00389
00390
00391 TXMLEngine::~TXMLEngine()
00392 {
00393
00394
00395 }
00396
00397
00398 Bool_t TXMLEngine::HasAttr(XMLNodePointer_t xmlnode, const char* name)
00399 {
00400
00401
00402 if ((xmlnode==0) || (name==0)) return kFALSE;
00403 SXmlAttr_t* attr = ((SXmlNode_t*)xmlnode)->fAttr;
00404 while (attr!=0) {
00405 if (strcmp(SXmlAttr_t::Name(attr),name)==0) return kTRUE;
00406 attr = attr->fNext;
00407 }
00408 return kFALSE;
00409 }
00410
00411
00412 const char* TXMLEngine::GetAttr(XMLNodePointer_t xmlnode, const char* name)
00413 {
00414
00415
00416 if (xmlnode==0) return 0;
00417 SXmlAttr_t* attr = ((SXmlNode_t*)xmlnode)->fAttr;
00418 while (attr!=0) {
00419 if (strcmp(SXmlAttr_t::Name(attr),name)==0)
00420 return SXmlAttr_t::Name(attr) + strlen(name) + 1;
00421 attr = attr->fNext;
00422 }
00423 return 0;
00424 }
00425
00426
00427 Int_t TXMLEngine::GetIntAttr(XMLNodePointer_t xmlnode, const char* name)
00428 {
00429
00430
00431 if (xmlnode==0) return 0;
00432 Int_t res = 0;
00433 const char* attr = GetAttr(xmlnode, name);
00434 if (attr) sscanf(attr, "%d", &res);
00435 return res;
00436 }
00437
00438
00439 XMLAttrPointer_t TXMLEngine::NewAttr(XMLNodePointer_t xmlnode, XMLNsPointer_t,
00440 const char* name, const char* value)
00441 {
00442
00443
00444
00445 if (xmlnode==0) return 0;
00446
00447 int namelen(name != 0 ? strlen(name) : 0);
00448 int valuelen(value != 0 ? strlen(value) : 0);
00449 SXmlAttr_t* attr = (SXmlAttr_t*) AllocateAttr(namelen, valuelen, xmlnode);
00450
00451 char* attrname = SXmlAttr_t::Name(attr);
00452 if (namelen>0)
00453 strncpy(attrname, name, namelen+1);
00454 else
00455 *attrname = 0;
00456 attrname += (namelen + 1);
00457 if (valuelen>0)
00458 strncpy(attrname, value, valuelen+1);
00459 else
00460 *attrname = 0;
00461
00462 return (XMLAttrPointer_t) attr;
00463 }
00464
00465
00466 XMLAttrPointer_t TXMLEngine::NewIntAttr(XMLNodePointer_t xmlnode,
00467 const char* name,
00468 Int_t value)
00469 {
00470
00471
00472 char sbuf[30];
00473 sprintf(sbuf,"%d",value);
00474 return NewAttr(xmlnode, 0, name, sbuf);
00475 }
00476
00477
00478 void TXMLEngine::FreeAttr(XMLNodePointer_t xmlnode, const char* name)
00479 {
00480
00481
00482 if (xmlnode==0) return;
00483 SXmlAttr_t* attr = ((SXmlNode_t*) xmlnode)->fAttr;
00484 SXmlAttr_t* prev = 0;
00485 while (attr!=0) {
00486 if (strcmp(SXmlAttr_t::Name(attr),name)==0) {
00487 if (prev!=0)
00488 prev->fNext = attr->fNext;
00489 else
00490 ((SXmlNode_t*) xmlnode)->fAttr = attr->fNext;
00491
00492 free(attr);
00493 return;
00494 }
00495
00496 prev = attr;
00497 attr = attr->fNext;
00498 }
00499 }
00500
00501
00502 void TXMLEngine::FreeAllAttr(XMLNodePointer_t xmlnode)
00503 {
00504
00505 if (xmlnode==0) return;
00506
00507 SXmlNode_t* node = (SXmlNode_t*) xmlnode;
00508 SXmlAttr_t* attr = node->fAttr;
00509 while (attr!=0) {
00510 SXmlAttr_t* next = attr->fNext;
00511 free(attr);
00512 attr = next;
00513 }
00514 node->fAttr = 0;
00515 }
00516
00517
00518
00519 XMLAttrPointer_t TXMLEngine::GetFirstAttr(XMLNodePointer_t xmlnode)
00520 {
00521
00522
00523 if (xmlnode==0) return 0;
00524 SXmlNode_t* node = (SXmlNode_t*) xmlnode;
00525
00526 SXmlAttr_t* attr = node->fAttr;
00527 if ((attr!=0) && (node->fNs==attr)) attr = attr->fNext;
00528
00529 return (XMLAttrPointer_t) attr;
00530 }
00531
00532
00533 XMLAttrPointer_t TXMLEngine::GetNextAttr(XMLAttrPointer_t xmlattr)
00534 {
00535
00536
00537 if (xmlattr==0) return 0;
00538
00539 return (XMLAttrPointer_t) ((SXmlAttr_t*) xmlattr)->fNext;
00540 }
00541
00542
00543 const char* TXMLEngine::GetAttrName(XMLAttrPointer_t xmlattr)
00544 {
00545
00546
00547 if (xmlattr==0) return 0;
00548
00549 return SXmlAttr_t::Name(xmlattr);
00550
00551 }
00552
00553
00554 const char* TXMLEngine::GetAttrValue(XMLAttrPointer_t xmlattr)
00555 {
00556
00557
00558 if (xmlattr==0) return 0;
00559
00560 const char* attrname = SXmlAttr_t::Name(xmlattr);
00561 return attrname + strlen(attrname) + 1;
00562 }
00563
00564
00565 XMLNodePointer_t TXMLEngine::NewChild(XMLNodePointer_t parent, XMLNsPointer_t ns,
00566 const char* name, const char* content)
00567 {
00568
00569
00570 int namelen(name!=0 ? strlen(name) : 0);
00571
00572 SXmlNode_t* node = (SXmlNode_t*) AllocateNode(namelen, parent);
00573
00574 if (namelen>0)
00575 strncpy(SXmlNode_t::Name(node), name, namelen+1);
00576 else
00577 *SXmlNode_t::Name(node) = 0;
00578
00579 node->fNs = (SXmlAttr_t*) ns;
00580 if (content!=0) {
00581 int contlen = strlen(content);
00582 if (contlen>0) {
00583 SXmlNode_t* contnode = (SXmlNode_t*) AllocateNode(contlen+1, node);
00584 char* cptr = SXmlNode_t::Name(contnode);
00585
00586 *cptr = 0;
00587 cptr++;
00588 strncpy(cptr, content, contlen+1);
00589 }
00590 }
00591
00592 return (XMLNodePointer_t) node;
00593 }
00594
00595
00596 XMLNsPointer_t TXMLEngine::NewNS(XMLNodePointer_t xmlnode, const char* reference, const char* name)
00597 {
00598
00599
00600
00601 SXmlNode_t* node = (SXmlNode_t*) xmlnode;
00602 if (name==0) name = SXmlNode_t::Name(node);
00603 int namelen = strlen(name);
00604 char* nsname = new char[namelen+7];
00605 snprintf(nsname, namelen+7, "xmlns:%s", name);
00606
00607 SXmlAttr_t* first = node->fAttr;
00608 node->fAttr = 0;
00609
00610 SXmlAttr_t* nsattr = (SXmlAttr_t*) NewAttr(xmlnode, 0, nsname, reference);
00611
00612 node->fAttr = nsattr;
00613 nsattr->fNext = first;
00614
00615 node->fNs = nsattr;
00616 delete[] nsname;
00617 return (XMLNsPointer_t) nsattr;
00618 }
00619
00620
00621 XMLNsPointer_t TXMLEngine::GetNS(XMLNodePointer_t xmlnode)
00622 {
00623
00624
00625 if (xmlnode==0) return 0;
00626 SXmlNode_t* node = (SXmlNode_t*) xmlnode;
00627
00628 return (XMLNsPointer_t) node->fNs;
00629 }
00630
00631
00632 const char* TXMLEngine::GetNSName(XMLNsPointer_t ns)
00633 {
00634
00635
00636 const char* nsname = GetAttrName((XMLAttrPointer_t)ns);
00637
00638 if ((nsname!=0) && (strncmp(nsname,"xmlns:",6)==0)) nsname+=6;
00639
00640 return nsname;
00641 }
00642
00643
00644 const char* TXMLEngine::GetNSReference(XMLNsPointer_t ns)
00645 {
00646
00647
00648 return GetAttrValue((XMLAttrPointer_t)ns);
00649 }
00650
00651
00652
00653 void TXMLEngine::AddChild(XMLNodePointer_t parent, XMLNodePointer_t child)
00654 {
00655
00656
00657 if ((parent==0) || (child==0)) return;
00658 SXmlNode_t* pnode = (SXmlNode_t*) parent;
00659 SXmlNode_t* cnode = (SXmlNode_t*) child;
00660 cnode->fParent = pnode;
00661 if (pnode->fLastChild==0) {
00662 pnode->fChild = cnode;
00663 pnode->fLastChild = cnode;
00664 } else {
00665
00666
00667 pnode->fLastChild->fNext = cnode;
00668 pnode->fLastChild = cnode;
00669 }
00670 }
00671
00672
00673 void TXMLEngine::AddChildFirst(XMLNodePointer_t parent, XMLNodePointer_t child)
00674 {
00675
00676
00677 if ((parent==0) || (child==0)) return;
00678 SXmlNode_t* pnode = (SXmlNode_t*) parent;
00679 SXmlNode_t* cnode = (SXmlNode_t*) child;
00680 cnode->fParent = pnode;
00681
00682 cnode->fNext = pnode->fChild;
00683 pnode->fChild = cnode;
00684
00685 if (pnode->fLastChild==0) pnode->fLastChild = cnode;
00686 }
00687
00688
00689
00690 Bool_t TXMLEngine::AddComment(XMLNodePointer_t xmlnode, const char* comment)
00691 {
00692
00693
00694 if ((xmlnode==0) || (comment==0)) return kFALSE;
00695
00696 int commentlen = strlen(comment);
00697
00698 SXmlNode_t* node = (SXmlNode_t*) AllocateNode(commentlen, xmlnode);
00699 node->fType = kXML_COMMENT;
00700 strncpy(SXmlNode_t::Name(node), comment, commentlen+1);
00701
00702 return kTRUE;
00703 }
00704
00705
00706 Bool_t TXMLEngine::AddDocComment(XMLDocPointer_t xmldoc, const char* comment)
00707 {
00708
00709
00710 if (xmldoc==0) return kFALSE;
00711
00712 XMLNodePointer_t rootnode = DocGetRootElement(xmldoc);
00713 UnlinkNode(rootnode);
00714
00715 bool res = AddComment(((SXmlDoc_t*)xmldoc)->fRootNode, comment);
00716
00717 AddChild((XMLNodePointer_t) ((SXmlDoc_t*)xmldoc)->fRootNode, rootnode);
00718
00719 return res;
00720 }
00721
00722
00723 Bool_t TXMLEngine::AddRawLine(XMLNodePointer_t xmlnode, const char* line)
00724 {
00725
00726
00727
00728
00729 if ((xmlnode==0) || (line==0)) return kFALSE;
00730
00731 int linelen = strlen(line);
00732 SXmlNode_t* node = (SXmlNode_t*) AllocateNode(linelen, xmlnode);
00733 node->fType = kXML_RAWLINE;
00734 strncpy(SXmlNode_t::Name(node), line, linelen+1);
00735
00736 return kTRUE;
00737 }
00738
00739
00740 Bool_t TXMLEngine::AddDocRawLine(XMLDocPointer_t xmldoc, const char* line)
00741 {
00742
00743
00744
00745 XMLNodePointer_t rootnode = DocGetRootElement(xmldoc);
00746 UnlinkNode(rootnode);
00747
00748 bool res = AddRawLine(((SXmlDoc_t*)xmldoc)->fRootNode, line);
00749
00750 AddChild((XMLNodePointer_t) ((SXmlDoc_t*)xmldoc)->fRootNode, rootnode);
00751
00752 return res;
00753
00754 }
00755
00756
00757
00758 Bool_t TXMLEngine::AddStyleSheet(XMLNodePointer_t xmlnode,
00759 const char* href,
00760 const char* type,
00761 const char* title,
00762 int alternate,
00763 const char* media,
00764 const char* charset)
00765 {
00766
00767
00768
00769
00770
00771
00772
00773
00774 if ((xmlnode==0) || (href==0) || (type==0)) return kFALSE;
00775
00776 const char* nodename = "xml-stylesheet";
00777 int nodenamelen = strlen(nodename);
00778
00779 SXmlNode_t* node = (SXmlNode_t*) AllocateNode(nodenamelen, xmlnode);
00780 node->fType = kXML_PI_NODE;
00781 strncpy(SXmlNode_t::Name(node), nodename, nodenamelen+1);
00782
00783 if (alternate>=0)
00784 NewAttr(node, 0, "alternate", (alternate>0) ? "yes" : "no");
00785
00786 if (title!=0) NewAttr(node, 0, "title", title);
00787
00788 NewAttr(node, 0, "href", href);
00789 NewAttr(node, 0, "type", type);
00790
00791 if (media!=0) NewAttr(node, 0, "media", media);
00792 if (charset!=0) NewAttr(node, 0, "charset", charset);
00793
00794 return kTRUE;
00795 }
00796
00797
00798
00799 Bool_t TXMLEngine::AddDocStyleSheet(XMLDocPointer_t xmldoc,
00800 const char* href,
00801 const char* type,
00802 const char* title,
00803 int alternate,
00804 const char* media,
00805 const char* charset)
00806 {
00807
00808
00809 if (xmldoc==0) return kFALSE;
00810
00811 XMLNodePointer_t rootnode = DocGetRootElement(xmldoc);
00812 UnlinkNode(rootnode);
00813
00814 bool res = AddStyleSheet(((SXmlDoc_t*)xmldoc)->fRootNode,
00815 href,type,title,alternate,media,charset);
00816
00817 AddChild((XMLNodePointer_t) ((SXmlDoc_t*)xmldoc)->fRootNode, rootnode);
00818
00819 return res;
00820 }
00821
00822
00823 void TXMLEngine::UnlinkNode(XMLNodePointer_t xmlnode)
00824 {
00825
00826
00827 if (xmlnode==0) return;
00828 SXmlNode_t* node = (SXmlNode_t*) xmlnode;
00829
00830 SXmlNode_t* parent = node->fParent;
00831
00832 if (parent==0) return;
00833
00834 if (parent->fChild==node) {
00835 parent->fChild = node->fNext;
00836 if (parent->fLastChild==node)
00837 parent->fLastChild = node->fNext;
00838 } else {
00839 SXmlNode_t* ch = parent->fChild;
00840 while (ch->fNext!=node) ch = ch->fNext;
00841 ch->fNext = node->fNext;
00842 if (parent->fLastChild == node)
00843 parent->fLastChild = ch;
00844 }
00845 }
00846
00847
00848 void TXMLEngine::FreeNode(XMLNodePointer_t xmlnode)
00849 {
00850
00851
00852
00853 if (xmlnode==0) return;
00854 SXmlNode_t* node = (SXmlNode_t*) xmlnode;
00855
00856 SXmlNode_t* child = node->fChild;
00857 while (child!=0) {
00858 SXmlNode_t* next = child->fNext;
00859 FreeNode((XMLNodePointer_t)child);
00860 child = next;
00861 }
00862
00863 SXmlAttr_t* attr = node->fAttr;
00864 while (attr!=0) {
00865 SXmlAttr_t* next = attr->fNext;
00866
00867 free(attr);
00868 attr = next;
00869 }
00870
00871 free(node);
00872
00873
00874 }
00875
00876
00877 void TXMLEngine::UnlinkFreeNode(XMLNodePointer_t xmlnode)
00878 {
00879
00880
00881 UnlinkNode(xmlnode);
00882 FreeNode(xmlnode);
00883 }
00884
00885
00886 const char* TXMLEngine::GetNodeName(XMLNodePointer_t xmlnode)
00887 {
00888
00889
00890 return xmlnode==0 ? 0 : SXmlNode_t::Name(xmlnode);
00891 }
00892
00893
00894 const char* TXMLEngine::GetNodeContent(XMLNodePointer_t xmlnode)
00895 {
00896
00897
00898 if (xmlnode==0) return 0;
00899 SXmlNode_t* node = (SXmlNode_t*) xmlnode;
00900 if (node->fChild==0) return 0;
00901 const char* childname = SXmlNode_t::Name(node->fChild);
00902 if ((childname==0) || (*childname != 0)) return 0;
00903 return childname + 1;
00904 }
00905
00906
00907 XMLNodePointer_t TXMLEngine::GetChild(XMLNodePointer_t xmlnode)
00908 {
00909
00910
00911 SXmlNode_t* res = xmlnode==0 ? 0 :((SXmlNode_t*) xmlnode)->fChild;
00912
00913 if ((res!=0) && (*SXmlNode_t::Name(res) == 0)) res = res->fNext;
00914 return (XMLNodePointer_t) res;
00915 }
00916
00917
00918 XMLNodePointer_t TXMLEngine::GetParent(XMLNodePointer_t xmlnode)
00919 {
00920
00921
00922 return xmlnode==0 ? 0 : (XMLNodePointer_t) ((SXmlNode_t*) xmlnode)->fParent;
00923 }
00924
00925
00926 XMLNodePointer_t TXMLEngine::GetNext(XMLNodePointer_t xmlnode)
00927 {
00928
00929
00930 return xmlnode==0 ? 0 : (XMLNodePointer_t) ((SXmlNode_t*) xmlnode)->fNext;
00931 }
00932
00933
00934 void TXMLEngine::ShiftToNext(XMLNodePointer_t &xmlnode, bool tonode)
00935 {
00936
00937
00938 do {
00939 xmlnode = xmlnode==0 ? 0 : (XMLNodePointer_t) ((SXmlNode_t*) xmlnode)->fNext;
00940 if ((xmlnode==0) || !tonode) return;
00941
00942 } while (((SXmlNode_t*) xmlnode)->fType != kXML_NODE);
00943 }
00944
00945
00946 Bool_t TXMLEngine::IsEmptyNode(XMLNodePointer_t xmlnode)
00947 {
00948
00949
00950 return xmlnode==0 ? kTRUE : (((SXmlNode_t*) xmlnode)->fType != kXML_NODE);
00951 }
00952
00953
00954 void TXMLEngine::SkipEmpty(XMLNodePointer_t &xmlnode)
00955 {
00956
00957
00958 if (IsEmptyNode(xmlnode)) ShiftToNext(xmlnode);
00959 }
00960
00961
00962
00963 void TXMLEngine::CleanNode(XMLNodePointer_t xmlnode)
00964 {
00965
00966
00967 if (xmlnode==0) return;
00968 SXmlNode_t* node = (SXmlNode_t*) xmlnode;
00969
00970 SXmlNode_t* child = node->fChild;
00971 while (child!=0) {
00972 SXmlNode_t* next = child->fNext;
00973 FreeNode((XMLNodePointer_t)child);
00974 child = next;
00975 }
00976
00977 node->fChild = 0;
00978 node->fLastChild = 0;
00979 }
00980
00981
00982 XMLDocPointer_t TXMLEngine::NewDoc(const char* version)
00983 {
00984
00985
00986 SXmlDoc_t* doc = new SXmlDoc_t;
00987 doc->fRootNode = (SXmlNode_t*) NewChild(0, 0, "??DummyTopNode??", 0);
00988
00989 if (version!=0) {
00990 XMLNodePointer_t vernode = NewChild( (XMLNodePointer_t) doc->fRootNode, 0, "xml");
00991 ((SXmlNode_t*) vernode)->fType = kXML_PI_NODE;
00992 NewAttr(vernode, 0, "version", version);
00993 }
00994
00995 doc->fDtdName = 0;
00996 doc->fDtdRoot = 0;
00997 return (XMLDocPointer_t) doc;
00998 }
00999
01000
01001 void TXMLEngine::AssignDtd(XMLDocPointer_t xmldoc, const char* dtdname, const char* rootname)
01002 {
01003
01004
01005 if (xmldoc==0) return;
01006 SXmlDoc_t* doc = (SXmlDoc_t*) xmldoc;
01007 delete[] doc->fDtdName;
01008 doc->fDtdName = Makestr(dtdname);
01009 delete[] doc->fDtdRoot;
01010 doc->fDtdRoot = Makestr(rootname);
01011 }
01012
01013
01014 void TXMLEngine::FreeDoc(XMLDocPointer_t xmldoc)
01015 {
01016
01017
01018 if (xmldoc==0) return;
01019 SXmlDoc_t* doc = (SXmlDoc_t*) xmldoc;
01020 FreeNode((XMLNodePointer_t) doc->fRootNode);
01021 delete[] doc->fDtdName;
01022 delete[] doc->fDtdRoot;
01023 delete doc;
01024 }
01025
01026
01027 void TXMLEngine::SaveDoc(XMLDocPointer_t xmldoc, const char* filename, Int_t layout)
01028 {
01029
01030
01031
01032
01033
01034
01035 if (xmldoc==0) return;
01036
01037 SXmlDoc_t* doc = (SXmlDoc_t*) xmldoc;
01038
01039 TXMLOutputStream out(filename, 100000);
01040
01041 XMLNodePointer_t child = GetChild((XMLNodePointer_t) doc->fRootNode);
01042
01043 do {
01044 SaveNode(child, &out, layout, 0);
01045 ShiftToNext(child, false);
01046 } while (child!=0);
01047
01048 }
01049
01050
01051 void TXMLEngine::DocSetRootElement(XMLDocPointer_t xmldoc, XMLNodePointer_t xmlnode)
01052 {
01053
01054
01055 if (xmldoc==0) return;
01056
01057 FreeNode(DocGetRootElement(xmldoc));
01058
01059 AddChild((XMLNodePointer_t) ((SXmlDoc_t*)xmldoc)->fRootNode, xmlnode);
01060 }
01061
01062
01063 XMLNodePointer_t TXMLEngine::DocGetRootElement(XMLDocPointer_t xmldoc)
01064 {
01065
01066
01067 if (xmldoc==0) return 0;
01068
01069 XMLNodePointer_t xmlnode = (XMLNodePointer_t) ((SXmlDoc_t*)xmldoc)->fRootNode;
01070
01071 xmlnode = GetChild(xmlnode);
01072
01073 ShiftToNext(xmlnode);
01074
01075 return xmlnode;
01076 }
01077
01078
01079 XMLDocPointer_t TXMLEngine::ParseFile(const char* filename)
01080 {
01081
01082
01083 if ((filename==0) || (strlen(filename)==0)) return 0;
01084 TXMLInputStream inp(true, filename, 100000);
01085 return ParseStream(&inp);
01086 }
01087
01088
01089 XMLDocPointer_t TXMLEngine::ParseString(const char* xmlstring)
01090 {
01091
01092
01093 if ((xmlstring==0) || (strlen(xmlstring)==0)) return 0;
01094 TXMLInputStream inp(false, xmlstring, 2*strlen(xmlstring) );
01095 return ParseStream(&inp);
01096 }
01097
01098
01099 XMLDocPointer_t TXMLEngine::ParseStream(TXMLInputStream* inp)
01100 {
01101
01102
01103 if (inp == 0) return 0;
01104
01105 XMLDocPointer_t xmldoc = NewDoc(0);
01106
01107 bool success = false;
01108
01109 Int_t resvalue = 0;
01110
01111 do {
01112 ReadNode(((SXmlDoc_t*) xmldoc)->fRootNode, inp, resvalue);
01113
01114 if (resvalue!=2) break;
01115
01116
01117 if (!inp->EndOfStream()) inp->SkipSpaces();
01118
01119 if (inp->EndOfStream()) {
01120 success = true;
01121 break;
01122 }
01123 } while (true);
01124
01125 if (!success) {
01126 DisplayError(resvalue, inp->CurrentLine());
01127 FreeDoc(xmldoc);
01128 return 0;
01129 }
01130
01131 return xmldoc;
01132 }
01133
01134
01135 Bool_t TXMLEngine::ValidateVersion(XMLDocPointer_t xmldoc, const char* version)
01136 {
01137
01138
01139 if (xmldoc==0) return kFALSE;
01140
01141 XMLNodePointer_t vernode = GetChild((XMLNodePointer_t) ((SXmlDoc_t*) xmldoc)->fRootNode);
01142 if (vernode==0) return kFALSE;
01143
01144 if (((SXmlNode_t*) vernode)->fType!=kXML_PI_NODE) return kFALSE;
01145 if (strcmp(GetNodeName(vernode), "xml")!=0) return kFALSE;
01146
01147 const char* value = GetAttr(vernode,"version");
01148 if (value==0) return kFALSE;
01149 if (version==0) version = "1.0";
01150
01151 return strcmp(version,value)==0;
01152 }
01153
01154
01155 void TXMLEngine::SaveSingleNode(XMLNodePointer_t xmlnode, TString* res, Int_t layout)
01156 {
01157
01158
01159
01160
01161
01162
01163 if ((res==0) || (xmlnode==0)) return;
01164
01165 TXMLOutputStream out(res, 10000);
01166
01167 SaveNode(xmlnode, &out, layout, 0);
01168 }
01169
01170
01171 XMLNodePointer_t TXMLEngine::ReadSingleNode(const char* src)
01172 {
01173
01174
01175 if (src==0) return 0;
01176
01177 TXMLInputStream inp(false, src, 10000);
01178
01179 Int_t resvalue;
01180
01181 XMLNodePointer_t xmlnode = ReadNode(0, &inp, resvalue);
01182
01183 if (resvalue<=0) {
01184 DisplayError(resvalue, inp.CurrentLine());
01185 FreeNode(xmlnode);
01186 return 0;
01187 }
01188
01189 return xmlnode;
01190 }
01191
01192
01193 char* TXMLEngine::Makestr(const char* str)
01194 {
01195
01196
01197 if (str==0) return 0;
01198 int len = strlen(str);
01199 if (len==0) return 0;
01200 char* res = new char[len+1];
01201 strncpy(res, str, len+1);
01202 return res;
01203 }
01204
01205
01206 char* TXMLEngine::Makenstr(const char* str, int len)
01207 {
01208
01209
01210 if ((str==0) || (len==0)) return 0;
01211 char* res = new char[len+1];
01212 strncpy(res, str, len);
01213 *(res+len) = 0;
01214 return res;
01215 }
01216
01217
01218 XMLNodePointer_t TXMLEngine::AllocateNode(int namelen, XMLNodePointer_t parent)
01219 {
01220
01221
01222
01223
01224 SXmlNode_t* node = (SXmlNode_t*) malloc(sizeof(SXmlNode_t) + namelen + 1);
01225
01226 node->fType = kXML_NODE;
01227 node->fParent = 0;
01228 node->fNs = 0;
01229 node->fAttr = 0;
01230 node->fChild = 0;
01231 node->fLastChild = 0;
01232 node->fNext = 0;
01233
01234 if (parent!=0)
01235 AddChild(parent, (XMLNodePointer_t) node);
01236
01237 return (XMLNodePointer_t) node;
01238 }
01239
01240
01241 XMLAttrPointer_t TXMLEngine::AllocateAttr(int namelen, int valuelen, XMLNodePointer_t xmlnode)
01242 {
01243
01244
01245
01246
01247 SXmlAttr_t* attr = (SXmlAttr_t*) malloc(sizeof(SXmlAttr_t) + namelen + 1 + valuelen + 1);
01248
01249 SXmlNode_t* node = (SXmlNode_t*) xmlnode;
01250
01251 attr->fNext = 0;
01252
01253 if (node->fAttr==0)
01254 node->fAttr = attr;
01255 else {
01256 SXmlAttr_t* d = node->fAttr;
01257 while (d->fNext!=0) d = d->fNext;
01258 d->fNext = attr;
01259 }
01260
01261 return (XMLAttrPointer_t) attr;
01262 }
01263
01264
01265 XMLNsPointer_t TXMLEngine::FindNs(XMLNodePointer_t xmlnode, const char* name)
01266 {
01267
01268
01269 SXmlNode_t* node = (SXmlNode_t*) xmlnode;
01270 while (node!=0) {
01271 if (node->fNs!=0) {
01272 const char* nsname = SXmlAttr_t::Name(node->fNs) + 6;
01273 if (strcmp(nsname, name)==0) return node->fNs;
01274 }
01275 node = node->fParent;
01276 }
01277 return 0;
01278 }
01279
01280
01281 void TXMLEngine::TruncateNsExtension(XMLNodePointer_t xmlnode)
01282 {
01283
01284
01285 SXmlNode_t* node = (SXmlNode_t*) xmlnode;
01286 if (node==0) return;
01287 char* colon = strchr(SXmlNode_t::Name(node),':');
01288 if (colon==0) return;
01289
01290 char* copyname = SXmlNode_t::Name(node);
01291
01292 while (*colon!=0)
01293 *(copyname++) = *(++colon);
01294 }
01295
01296
01297 void TXMLEngine::UnpackSpecialCharacters(char* target, const char* source, int srclen)
01298 {
01299
01300
01301
01302 while (srclen>0) {
01303 if (*source=='&') {
01304 if ((*(source+1)=='l') && (*(source+2)=='t') && (*(source+3)==';')) {
01305 *target++ = '<'; source+=4; srclen-=4;
01306 } else
01307 if ((*(source+1)=='g') && (*(source+2)=='t') && (*(source+3)==';')) {
01308 *target++ = '>'; source+=4; srclen-=4;
01309 } else
01310 if ((*(source+1)=='a') && (*(source+2)=='m') && (*(source+3)=='p') && (*(source+4)==';')) {
01311 *target++ = '&'; source+=5; srclen-=5;
01312 } else
01313 if ((*(source+1)=='q') && (*(source+2)=='u') && (*(source+3)=='o') && (*(source+4)=='t') && (*(source+5)==';')) {
01314 *target++ = '\"'; source+=6; srclen-=6;
01315 } else {
01316 *target++ = *source++; srclen--;
01317 }
01318 } else {
01319 *target++ = *source++;
01320 srclen--;
01321 }
01322 }
01323 *target = 0;
01324 }
01325
01326
01327 void TXMLEngine::OutputValue(char* value, TXMLOutputStream* out)
01328 {
01329
01330
01331
01332
01333 if (value==0) return;
01334
01335 char* last = value;
01336 char* find = 0;
01337 while ((find=strpbrk(last,"<&>\"")) !=0 ) {
01338 char symb = *find;
01339 *find = 0;
01340 out->Write(last);
01341 *find = symb;
01342 last = find+1;
01343 if (symb=='<') out->Write("<");
01344 else if (symb=='>') out->Write(">");
01345 else if (symb=='&') out->Write("&");
01346 else out->Write(""");
01347 }
01348 if (*last!=0)
01349 out->Write(last);
01350 }
01351
01352
01353 void TXMLEngine::SaveNode(XMLNodePointer_t xmlnode, TXMLOutputStream* out, Int_t layout, Int_t level)
01354 {
01355
01356
01357 if (xmlnode==0) return;
01358 SXmlNode_t* node = (SXmlNode_t*) xmlnode;
01359
01360
01361 if (*SXmlNode_t::Name(node) == 0 ) {
01362 out->Write(SXmlNode_t::Name(node)+1);
01363 return;
01364 }
01365
01366 Bool_t issingleline = (node->fChild==0);
01367
01368 if (layout>0) out->Put(' ', level);
01369
01370 if (node->fType==kXML_COMMENT) {
01371 out->Write("<!--");
01372 out->Write(SXmlNode_t::Name(node));
01373 out->Write("-->");
01374 if (layout>0) out->Put('\n');
01375 return;
01376 } else
01377 if (node->fType==kXML_RAWLINE) {
01378 out->Write(SXmlNode_t::Name(node));
01379 if (layout>0) out->Put('\n');
01380 return;
01381 }
01382
01383 out->Put('<');
01384 if (node->fType==kXML_PI_NODE) out->Put('?');
01385
01386
01387 if ((node->fNs!=0) && (node->fNs!=node->fAttr)) {
01388 out->Write(SXmlAttr_t::Name(node->fNs)+6);
01389 out->Put(':');
01390 }
01391 out->Write(SXmlNode_t::Name(node));
01392
01393 SXmlAttr_t* attr = node->fAttr;
01394 while (attr!=0) {
01395 out->Put(' ');
01396 char* attrname = SXmlAttr_t::Name(attr);
01397 out->Write(attrname);
01398 out->Write("=\"");
01399 attrname += strlen(attrname) + 1;
01400 OutputValue(attrname, out);
01401 out->Put('\"');
01402 attr = attr->fNext;
01403 }
01404
01405
01406 if (issingleline) {
01407 if (node->fType==kXML_PI_NODE) out->Write("?>");
01408 else out->Write("/>");
01409 if (layout>0) out->Put('\n');
01410 return;
01411 }
01412
01413 out->Put('>');
01414
01415
01416 const char* content = GetNodeContent(xmlnode);
01417 if ((content==0) && (layout>0))
01418 out->Put('\n');
01419
01420 if (content!=0) out->Write(content);
01421
01422 SXmlNode_t* child = (SXmlNode_t*) GetChild(xmlnode);
01423 while (child!=0) {
01424 if (content!=0) {
01425 content = 0;
01426 if (layout>0) out->Put('\n');
01427 }
01428 SaveNode((XMLNodePointer_t) child, out, layout, level+2);
01429 child = child->fNext;
01430 }
01431
01432
01433 if ((content==0) && (layout>0)) out->Put(' ',level);
01434
01435 out->Write("</");
01436
01437 if ((node->fNs!=0) && (node->fNs!=node->fAttr)) {
01438 out->Write(SXmlAttr_t::Name(node->fNs)+6);
01439 out->Put(':');
01440 }
01441 out->Write(SXmlNode_t::Name(node));
01442 out->Put('>');
01443 if (layout>0) out->Put('\n');
01444 }
01445
01446
01447 XMLNodePointer_t TXMLEngine::ReadNode(XMLNodePointer_t xmlparent, TXMLInputStream* inp, Int_t& resvalue)
01448 {
01449
01450
01451
01452
01453
01454
01455 resvalue = 0;
01456
01457 if (inp==0) return 0;
01458 if (!inp->SkipSpaces()) { resvalue = -1; return 0; }
01459 SXmlNode_t* parent = (SXmlNode_t*) xmlparent;
01460
01461 SXmlNode_t* node = 0;
01462
01463
01464 while (inp->CheckFor("<!--")) {
01465 Int_t commentlen = inp->SearchFor("-->");
01466 if (commentlen<=0) { resvalue = -10; return 0; }
01467
01468 if (!fSkipComments) {
01469 node = (SXmlNode_t*) AllocateNode(commentlen, xmlparent);
01470 char* nameptr = SXmlNode_t::Name(node);
01471 node->fType = kXML_COMMENT;
01472 strncpy(nameptr, inp->fCurrent, commentlen);
01473 nameptr+=commentlen;
01474 *nameptr = 0;
01475 }
01476
01477 if (!inp->ShiftCurrent(commentlen+3)) { resvalue = -1; return node; }
01478 if (!inp->SkipSpaces()) { resvalue = -1; return node; }
01479
01480 resvalue = 2;
01481 return node;
01482 }
01483
01484 if (*inp->fCurrent!='<') {
01485
01486
01487 if ((parent==0) || (parent->fChild!=0)) { resvalue = -2; return 0; }
01488 int contlen = inp->LocateContent();
01489 if (contlen<0) return 0;
01490
01491 SXmlNode_t* contnode = (SXmlNode_t*) AllocateNode(contlen+1, xmlparent);
01492 char* contptr = SXmlNode_t::Name(contnode);
01493 *contptr = 0;
01494 contptr++;
01495 UnpackSpecialCharacters(contptr, inp->fCurrent, contlen);
01496 if (!inp->ShiftCurrent(contlen)) return 0;
01497 resvalue = 2;
01498 return contnode;
01499 } else
01500
01501 if (!inp->ShiftCurrent()) return 0;
01502
01503 if (*inp->fCurrent=='/') {
01504
01505 if (!inp->ShiftCurrent()) return 0;
01506 if (!inp->SkipSpaces()) return 0;
01507 Int_t len = inp->LocateIdentifier();
01508 if (len<=0) { resvalue = -3; return 0; }
01509
01510 if (parent==0) { resvalue = -4; return 0; }
01511
01512 if (strncmp(SXmlNode_t::Name(parent), inp->fCurrent, len)!=0) {
01513 resvalue = -5;
01514 return 0;
01515 }
01516
01517 if (!inp->ShiftCurrent(len)) return 0;
01518
01519 if (!inp->SkipSpaces()) return 0;
01520 if (*inp->fCurrent!='>') return 0;
01521 if (!inp->ShiftCurrent()) return 0;
01522
01523 if (parent->fNs!=0)
01524 TruncateNsExtension((XMLNodePointer_t)parent);
01525
01526 inp->SkipSpaces(kTRUE);
01527 resvalue = 1;
01528 return 0;
01529 }
01530
01531 EXmlNodeType nodetype = kXML_NODE;
01532 bool canhaschilds = true;
01533 char endsymbol = '/';
01534
01535
01536 if (*inp->fCurrent=='?') {
01537 if (!inp->ShiftCurrent()) return 0;
01538 nodetype = kXML_PI_NODE;
01539 canhaschilds = false;
01540 endsymbol = '?';
01541 }
01542
01543 if (!inp->SkipSpaces()) return 0;
01544 Int_t len = inp->LocateIdentifier();
01545 if (len<=0) return 0;
01546 node = (SXmlNode_t*) AllocateNode(len, xmlparent);
01547 char* nameptr = SXmlNode_t::Name(node);
01548 node->fType = nodetype;
01549
01550 strncpy(nameptr, inp->fCurrent, len);
01551 nameptr+=len;
01552 *nameptr = 0;
01553
01554 char* colon = strchr(SXmlNode_t::Name(node),':');
01555 if ((colon!=0) && (parent!=0)) {
01556 *colon = 0;
01557 node->fNs = (SXmlAttr_t*) FindNs(xmlparent, SXmlNode_t::Name(node));
01558 *colon =':';
01559 }
01560
01561 if (!inp->ShiftCurrent(len)) return 0;
01562
01563 do {
01564 if (!inp->SkipSpaces()) return 0;
01565
01566 char nextsymb = *inp->fCurrent;
01567
01568 if (nextsymb==endsymbol) {
01569 if (!inp->ShiftCurrent()) return 0;
01570 if (*inp->fCurrent=='>') {
01571 if (!inp->ShiftCurrent()) return 0;
01572
01573 if (node->fNs!=0)
01574 TruncateNsExtension((XMLNodePointer_t) node);
01575
01576 inp->SkipSpaces(kTRUE);
01577 resvalue = 2;
01578 return node;
01579 } else return 0;
01580 } else
01581 if (nextsymb=='>') {
01582 if (!canhaschilds) { resvalue = -11; return 0; }
01583
01584 if (!inp->ShiftCurrent()) return 0;
01585
01586 do {
01587 ReadNode(node, inp, resvalue);
01588 } while (resvalue==2);
01589
01590 if (resvalue==1) {
01591 resvalue = 2;
01592 return node;
01593 } else return 0;
01594 } else {
01595 Int_t attrlen = inp->LocateIdentifier();
01596 if (attrlen<=0) { resvalue = -6; return 0; }
01597
01598 char* valuestart = inp->fCurrent+attrlen;
01599
01600 int valuelen = inp->LocateAttributeValue(valuestart);
01601 if (valuelen<3) { resvalue = -7; return 0; }
01602
01603 SXmlAttr_t* attr = (SXmlAttr_t*) AllocateAttr(attrlen, valuelen-3, (XMLNodePointer_t) node);
01604
01605 char* attrname = SXmlAttr_t::Name(attr);
01606 strncpy(attrname, inp->fCurrent, attrlen);
01607 attrname+=attrlen;
01608 *attrname = 0;
01609 attrname++;
01610 UnpackSpecialCharacters(attrname, valuestart+2, valuelen-3);
01611
01612 if (!inp->ShiftCurrent(attrlen+valuelen)) return 0;
01613
01614 attrname = SXmlAttr_t::Name(attr);
01615
01616 if ((strlen(attrname)>6) && (strstr(attrname,"xmlns:")==attrname)) {
01617 if (strcmp(SXmlNode_t::Name(node), attrname + 6)!=0) {
01618 resvalue = -8;
01619
01620 }
01621 if (node->fNs!=0) {
01622 resvalue = -9;
01623
01624 }
01625 node->fNs = attr;
01626 }
01627 }
01628 } while (true);
01629
01630 return 0;
01631 }
01632
01633
01634 void TXMLEngine::DisplayError(Int_t error, Int_t linenumber)
01635 {
01636
01637 switch(error) {
01638 case -11: Error("ParseFile", "Node cannot be closed with > symbol at line %d, for instance <?xml ... ?> node", linenumber); break;
01639 case -10: Error("ParseFile", "Error in xml comments definition at line %d, must be <!-- comments -->", linenumber); break;
01640 case -9: Error("ParseFile", "Multiple name space definitions not allowed, line %d", linenumber); break;
01641 case -8: Error("ParseFile", "Invalid namespace specification, line %d", linenumber); break;
01642 case -7: Error("ParseFile", "Invalid attribute value, line %d", linenumber); break;
01643 case -6: Error("ParseFile", "Invalid identifier for node attribute, line %d", linenumber); break;
01644 case -5: Error("ParseFile", "Missmatch between open and close nodes, line %d", linenumber); break;
01645 case -4: Error("ParseFile", "Unexpected close node, line %d", linenumber); break;
01646 case -3: Error("ParseFile", "Valid identifier for close node is missing, line %d", linenumber); break;
01647 case -2: Error("ParseFile", "No multiple content entries allowed, line %d", linenumber); break;
01648 case -1: Error("ParseFile", "Unexpected end of xml file"); break;
01649 default: Error("ParseFile", "XML syntax error at line %d", linenumber); break;
01650 }
01651
01652 }
01653