Logo ROOT   6.16/01
Reference Guide
TXMLEngine.cxx
Go to the documentation of this file.
1// @(#)root/xml:$Id: 1bd040ac1c03c58bcad15b5206d602680a831c0a $
2// Author: Sergey Linev 10.05.2004
3
4/*************************************************************************
5 * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12//________________________________________________________________________
13//
14// TXMLEngine class is used to write and read ROOT XML files - TXMLFile.
15// It does not conform to complete xml standard and cannot be used
16// as parser for arbitrary XML files. For such cases TXMLParser should
17// be used. This class was introduced to exclude dependency from
18// external libraries (like libxml2) and improve speed / memory consumption.
19//
20//________________________________________________________________________
21
22#include "TXMLEngine.h"
23
24#include "Riostream.h"
25#include "TString.h"
26#include "TNamed.h"
27#include "TObjArray.h"
28#include <stdlib.h>
29#include <string.h>
30
32
33struct SXmlAttr_t {
34 SXmlAttr_t *fNext;
35 // after structure itself memory for attribute name is preserved
36 // if first byte is 0, this is special attribute
37 static inline char *Name(void *arg) { return (char *)arg + sizeof(SXmlAttr_t); }
38};
39
41 kXML_NODE = 1, // normal node with children
42 kXML_COMMENT = 2, // comment (stored as value of node fName)
43 kXML_PI_NODE = 3, // processing instructions node (like <?name attr="" ?>
44 kXML_RAWLINE = 4, // just one line of xml code
45 kXML_CONTENT = 5 // node content, can appear many times in between of normal nodes
46};
47
48struct SXmlNode_t {
49 EXmlNodeType fType; // this is node type - node, comment, processing instruction and so on
50 SXmlAttr_t *fAttr; // first attribute
51 SXmlAttr_t *fNs; // name space definition (if any)
52 SXmlNode_t *fNext; // next node on the same level of hierarchy
53 SXmlNode_t *fChild; // first child node
54 SXmlNode_t *fLastChild; // last child node
55 SXmlNode_t *fParent; // parent node
56 // consequent bytes after structure are node name
57 // if first byte is 0, next is node content
58 static inline char *Name(void *arg) { return (char *)arg + sizeof(SXmlNode_t); }
59};
60
61struct SXmlDoc_t {
62 SXmlNode_t *fRootNode;
63 char *fDtdName;
64 char *fDtdRoot;
65};
66
67class TXMLOutputStream {
68protected:
69 std::ostream *fOut;
70 TString *fOutStr;
71 char *fBuf;
72 char *fCurrent;
73 char *fMaxAddr;
74 char *fLimitAddr;
75
76public:
77 TXMLOutputStream(const char *filename, Int_t bufsize = 20000)
78 {
79 fOut = new std::ofstream(filename);
80 fOutStr = 0;
81 Init(bufsize);
82 }
83
84 TXMLOutputStream(TString *outstr, Int_t bufsize = 20000)
85 {
86 fOut = 0;
87 fOutStr = outstr;
88 Init(bufsize);
89 }
90
91 void Init(Int_t bufsize)
92 {
93 fBuf = (char *)malloc(bufsize);
94 fCurrent = fBuf;
95 fMaxAddr = fBuf + bufsize;
96 fLimitAddr = fBuf + int(bufsize * 0.75);
97 }
98
99 virtual ~TXMLOutputStream()
100 {
101 if (fCurrent != fBuf)
102 OutputCurrent();
103 delete fOut;
104 free(fBuf);
105 }
106
107 void OutputCurrent()
108 {
109 if (fCurrent != fBuf) {
110 if (fOut != 0)
111 fOut->write(fBuf, fCurrent - fBuf);
112 else if (fOutStr != 0)
113 fOutStr->Append(fBuf, fCurrent - fBuf);
114 }
115 fCurrent = fBuf;
116 }
117
118 void OutputChar(char symb)
119 {
120 if (fOut != 0)
121 fOut->put(symb);
122 else if (fOutStr != 0)
123 fOutStr->Append(symb);
124 }
125
126 void Write(const char *str)
127 {
128 int len = strlen(str);
129 if (fCurrent + len >= fMaxAddr) {
130 OutputCurrent();
131 fOut->write(str, len);
132 } else {
133 while (*str)
134 *fCurrent++ = *str++;
135 if (fCurrent > fLimitAddr)
136 OutputCurrent();
137 }
138 }
139
140 void Put(char symb, Int_t cnt = 1)
141 {
142 if (fCurrent + cnt >= fMaxAddr)
143 OutputCurrent();
144 if (fCurrent + cnt >= fMaxAddr)
145 for (int n = 0; n < cnt; n++)
146 OutputChar(symb);
147 else {
148 for (int n = 0; n < cnt; n++)
149 *fCurrent++ = symb;
150 if (fCurrent > fLimitAddr)
151 OutputCurrent();
152 }
153 }
154};
155
156class TXMLEntity : public TNamed {
157 Bool_t fSystem; //! is system (file)
158public:
159 TXMLEntity() : TNamed(), fSystem(kFALSE) {}
160 TXMLEntity(const TString &name, const TString &value, Bool_t sys) : TNamed(name, value), fSystem(sys) {}
161 Bool_t IsSystem() const { return fSystem; }
162};
163
164class TXMLInputStream {
165protected:
166 std::istream *fInp;
167 const char *fInpStr;
168 Int_t fInpStrLen;
169
170 char *fBuf;
171 Int_t fBufSize;
172
173 char *fMaxAddr;
174 char *fLimitAddr;
175
176 Int_t fTotalPos;
177 Int_t fCurrentLine;
178
179 TObjArray fEntities; //! array of TXMLEntity
180
181public:
182 char *fCurrent;
183
184 ////////////////////////////////////////////////////////////////////////////
185 /// constructor
186
187 TXMLInputStream(Bool_t isfilename, const char *filename, Int_t ibufsize)
188 : fInp(0), fInpStr(0), fInpStrLen(0), fBuf(0), fBufSize(0), fMaxAddr(0), fLimitAddr(0), fTotalPos(0),
189 fCurrentLine(0), fEntities(), fCurrent(0)
190 {
191 if (isfilename) {
192 fInp = new std::ifstream(filename);
193 fInpStr = 0;
194 fInpStrLen = 0;
195 } else {
196 fInp = 0;
197 fInpStr = filename;
198 fInpStrLen = filename == 0 ? 0 : strlen(filename);
199 }
200
201 fBufSize = ibufsize;
202 fBuf = (char *)malloc(fBufSize);
203
204 fCurrent = 0;
205 fMaxAddr = 0;
206
207 int len = DoRead(fBuf, fBufSize);
208 fCurrent = fBuf;
209 fMaxAddr = fBuf + len;
210 fLimitAddr = fBuf + int(len * 0.75);
211
212 fTotalPos = 0;
213 fCurrentLine = 1;
214
215 fEntities.SetOwner(kTRUE);
216 }
217
218 ////////////////////////////////////////////////////////////////////////////
219 /// destructor
220
221 virtual ~TXMLInputStream()
222 {
223 delete fInp;
224 fInp = 0;
225 free(fBuf);
226 fBuf = 0;
227 }
228
229 ////////////////////////////////////////////////////////////////////////////
230 /// return true if end of file is achieved
231
232 inline Bool_t EndOfFile() { return (fInp != 0) ? fInp->eof() : (fInpStrLen <= 0); }
233
234 ////////////////////////////////////////////////////////////////////////////
235 /// return true if end of file and all data from buffer are processed
236
237 inline Bool_t EndOfStream() { return EndOfFile() && (fCurrent >= fMaxAddr); }
238
239 ////////////////////////////////////////////////////////////////////////////
240 /// Add new entity
241
242 void AddEntity(TXMLEntity *ent) { fEntities.Add(ent); }
243
244 ////////////////////////////////////////////////////////////////////////////
245 /// Returns number of entity
246
247 Int_t NumEntities() const { return fEntities.GetLast() + 1; }
248
249 ////////////////////////////////////////////////////////////////////////////
250 /// Search for the entity
251
252 TXMLEntity *FindEntity(const char *beg, Int_t len)
253 {
254 if (len <= 0)
255 return 0;
256 for (Int_t n = 0; n <= fEntities.GetLast(); n++) {
257 TXMLEntity *entity = (TXMLEntity *)fEntities[n];
258 if ((Int_t)strlen(entity->GetName()) != len)
259 continue;
260 if (strncmp(beg, entity->GetName(), len) == 0)
261 return entity;
262 }
263 return 0;
264 }
265
266 ////////////////////////////////////////////////////////////////////////////
267 /// Read new data into buffer
268
269 int DoRead(char *buf, int maxsize)
270 {
271 if (EndOfFile())
272 return 0;
273 if (fInp != 0) {
274 fInp->get(buf, maxsize, 0);
275 maxsize = strlen(buf);
276 } else {
277 if (maxsize > fInpStrLen)
278 maxsize = fInpStrLen;
279 strncpy(buf, fInpStr, maxsize);
280 fInpStr += maxsize;
281 fInpStrLen -= maxsize;
282 }
283 return maxsize;
284 }
285
286 ////////////////////////////////////////////////////////////////////////////
287 /// Allocate more data for the buffer, preserving content
288
289 Bool_t ExpandStream(char *&curr)
290 {
291 if (EndOfFile())
292 return kFALSE;
293 fBufSize *= 2;
294 int curlength = fMaxAddr - fBuf;
295 char *newbuf = (char *)realloc(fBuf, fBufSize);
296 if (!newbuf)
297 return kFALSE;
298
299 fMaxAddr = newbuf + (fMaxAddr - fBuf);
300 fCurrent = newbuf + (fCurrent - fBuf);
301 fLimitAddr = newbuf + (fLimitAddr - fBuf);
302 curr = newbuf + (curr - fBuf);
303 fBuf = newbuf;
304
305 int len = DoRead(fMaxAddr, fBufSize - curlength);
306 if (len == 0)
307 return kFALSE;
308 fMaxAddr += len;
309 fLimitAddr += int(len * 0.75);
310 return kTRUE;
311 }
312
313 ////////////////////////////////////////////////////////////////////////////
314 /// read next portion of data from the stream in the buffer
315
316 Bool_t ShiftStream()
317 {
318 if (fCurrent < fLimitAddr)
319 return kTRUE; // everything ok, can continue
320 if (EndOfFile())
321 return kTRUE;
322 int rest_len = fMaxAddr - fCurrent;
323 memmove(fBuf, fCurrent, rest_len);
324 int read_len = DoRead(fBuf + rest_len, fBufSize - rest_len);
325
326 fCurrent = fBuf;
327 fMaxAddr = fBuf + rest_len + read_len;
328 fLimitAddr = fBuf + int((rest_len + read_len) * 0.75);
329 return kTRUE;
330 }
331
332 ////////////////////////////////////////////////////////////////////////////
333 /// returns absolute byte position in the stream
334
335 Int_t TotalPos() { return fTotalPos; }
336
337 ////////////////////////////////////////////////////////////////////////////
338 /// returns current line number in the input stream
339
340 Int_t CurrentLine() { return fCurrentLine; }
341
342 ////////////////////////////////////////////////////////////////////////////
343 /// shift current position on provided number of symbol
344
345 Bool_t ShiftCurrent(Int_t sz = 1)
346 {
347 for (int n = 0; n < sz; n++) {
348 if (*fCurrent == 10)
349 fCurrentLine++;
350 if (fCurrent >= fLimitAddr) {
351 ShiftStream();
352 if (fCurrent >= fMaxAddr)
353 return kFALSE;
354 }
355 fCurrent++;
356 }
357 fTotalPos += sz;
358 return kTRUE;
359 }
360
361 ////////////////////////////////////////////////////////////////////////////
362 /// Skip spaces at the current position
363
364 Bool_t SkipSpaces(Bool_t tillendl = kFALSE)
365 {
366 while (fCurrent < fMaxAddr) {
367 char symb = *fCurrent;
368 if ((symb > 26) && (symb != ' '))
369 return kTRUE;
370
371 if (!ShiftCurrent())
372 return kFALSE;
373
374 if (tillendl && (symb == 10))
375 return kTRUE;
376 }
377 return kFALSE;
378 }
379
380 /////////////////////////////////////////////////////////////
381 /// Check if in current position we see specified string
382
383 Bool_t CheckFor(const char *str)
384 {
385 int len = strlen(str);
386 char *curr = fCurrent;
387 while (curr + len > fMaxAddr) {
388 if (!ExpandStream(curr))
389 return kFALSE;
390 }
391 while (*str != 0)
392 if (*str++ != *curr++)
393 return kFALSE;
394 return ShiftCurrent(len);
395 }
396
397 /////////////////////////////////////////////////////////////////////
398 /// Search for specified string in the stream
399 /// return number of symbols before string was found, -1 if error
400
401 Int_t SearchFor(const char *str)
402 {
403 int len = strlen(str);
404
405 char *curr = fCurrent;
406
407 do {
408 curr++;
409 while (curr + len > fMaxAddr)
410 if (!ExpandStream(curr))
411 return -1;
412 char *chk0 = curr;
413 const char *chk = str;
414 Bool_t find = kTRUE;
415 while (*chk != 0)
416 if (*chk++ != *chk0++) {
417 find = kFALSE;
418 break;
419 }
420 // if string found, shift to the next symbol after string
421 if (find)
422 return curr - fCurrent;
423 } while (curr < fMaxAddr);
424 return -1;
425 }
426
427 ////////////////////////////////////////////////////////////////////////////
428 /// returns true if symbol can be used as starting in the node name
429
430 inline Bool_t GoodStartSymbol(unsigned char symb)
431 {
432 return (((symb >= 'a') && (symb <= 'z')) || ((symb >= 'A') && (symb <= 'Z')) || (symb == '_') ||
433 ((symb >= 0xc0) && (symb <= 0xd6)) || ((symb >= 0xd8) && (symb <= 0xf6)) || (symb > 0xf8));
434 }
435
436 ////////////////////////////////////////////////////////////////////////////
437 /// locate identifier in the stream, returns length of the identifier (or 0 if fails)
438
439 Int_t LocateIdentifier()
440 {
441 unsigned char symb = (unsigned char)*fCurrent;
442
443 Bool_t ok = GoodStartSymbol(symb);
444 if (!ok)
445 return 0;
446
447 char *curr = fCurrent;
448
449 do {
450 curr++;
451 if (curr >= fMaxAddr)
452 if (!ExpandStream(curr))
453 return 0;
454 symb = (unsigned char)*curr;
455 ok = GoodStartSymbol(symb) || ((symb >= '0') && (symb <= '9')) || (symb == ':') || (symb == '-') ||
456 (symb == '.') || (symb == 0xb7);
457 if (!ok)
458 return curr - fCurrent;
459 } while (curr < fMaxAddr);
460 return 0;
461 }
462
463 ////////////////////////////////////////////////////////////////////////////
464 /// locate node content, returns length (or -1 if fails)
465
466 Int_t LocateContent()
467 {
468 char *curr = fCurrent;
469 while (curr < fMaxAddr) {
470 char symb = *curr;
471 if (symb == '<')
472 return curr - fCurrent;
473 curr++;
474 if (curr >= fMaxAddr)
475 if (!ExpandStream(curr))
476 return -1;
477 }
478 return -1;
479 }
480
481 ////////////////////////////////////////////////////////////////////////////
482 /// locate attribute value, returns length (or 0 if fails)
483
484 Int_t LocateValue(unsigned curr_offset, bool withequalsign = true)
485 {
486 char *curr = fCurrent + curr_offset;
487 if (curr >= fMaxAddr)
488 if (!ExpandStream(curr))
489 return 0;
490 if (withequalsign) {
491 if (*curr != '=')
492 return 0;
493 curr++;
494 if (curr >= fMaxAddr)
495 if (!ExpandStream(curr))
496 return 0;
497 }
498 if ((*curr != '\"') && (*curr != '\''))
499 return 0;
500 char quote = *curr;
501 do {
502 curr++;
503 if (curr >= fMaxAddr)
504 if (!ExpandStream(curr))
505 return 0;
506 if (*curr == quote)
507 return curr - (fCurrent + curr_offset) + 1;
508 } while (curr < fMaxAddr);
509 return 0;
510 }
511};
512
513////////////////////////////////////////////////////////////////////////////////
514/// default (normal) constructor of TXMLEngine class
515
517{
519}
520
521////////////////////////////////////////////////////////////////////////////////
522/// destructor for TXMLEngine object
523
525{
526}
527
528////////////////////////////////////////////////////////////////////////////////
529/// checks if node has attribute of specified name
530
532{
533 if ((xmlnode == 0) || (name == 0))
534 return kFALSE;
535 SXmlAttr_t *attr = ((SXmlNode_t *)xmlnode)->fAttr;
536 while (attr != 0) {
537 if (strcmp(SXmlAttr_t::Name(attr), name) == 0)
538 return kTRUE;
539 attr = attr->fNext;
540 }
541 return kFALSE;
542}
543
544////////////////////////////////////////////////////////////////////////////////
545/// returns value of attribute for xmlnode
546
547const char *TXMLEngine::GetAttr(XMLNodePointer_t xmlnode, const char *name)
548{
549 if (xmlnode == 0)
550 return 0;
551 SXmlAttr_t *attr = ((SXmlNode_t *)xmlnode)->fAttr;
552 while (attr != 0) {
553 if (strcmp(SXmlAttr_t::Name(attr), name) == 0)
554 return SXmlAttr_t::Name(attr) + strlen(name) + 1;
555 attr = attr->fNext;
556 }
557 return 0;
558}
559
560////////////////////////////////////////////////////////////////////////////////
561/// returns value of attribute as integer
562
564{
565 if (xmlnode == 0)
566 return 0;
567 Int_t res = 0;
568 const char *attr = GetAttr(xmlnode, name);
569 if (attr)
570 sscanf(attr, "%d", &res);
571 return res;
572}
573
574////////////////////////////////////////////////////////////////////////////////
575/// creates new attribute for xmlnode,
576/// namespaces are not supported for attributes
577
579{
580 if (xmlnode == 0)
581 return 0;
582
583 int namelen(name != 0 ? strlen(name) : 0);
584 int valuelen(value != 0 ? strlen(value) : 0);
585 SXmlAttr_t *attr = (SXmlAttr_t *)AllocateAttr(namelen, valuelen, xmlnode);
586
587 char *attrname = SXmlAttr_t::Name(attr);
588 if (namelen > 0)
589 strncpy(attrname, name, namelen + 1);
590 else
591 *attrname = 0;
592 attrname += (namelen + 1);
593 if (valuelen > 0)
594 strncpy(attrname, value, valuelen + 1);
595 else
596 *attrname = 0;
597
598 return (XMLAttrPointer_t)attr;
599}
600
601////////////////////////////////////////////////////////////////////////////////
602/// create node attribute with integer value
603
605{
606 char sbuf[30];
607 sprintf(sbuf, "%d", value);
608 return NewAttr(xmlnode, 0, name, sbuf);
609}
610
611////////////////////////////////////////////////////////////////////////////////
612/// remove attribute from xmlnode
613
615{
616 if (xmlnode == 0)
617 return;
618 SXmlAttr_t *attr = ((SXmlNode_t *)xmlnode)->fAttr;
619 SXmlAttr_t *prev = 0;
620 while (attr != 0) {
621 if (strcmp(SXmlAttr_t::Name(attr), name) == 0) {
622 if (prev != 0)
623 prev->fNext = attr->fNext;
624 else
625 ((SXmlNode_t *)xmlnode)->fAttr = attr->fNext;
626 // fNumNodes--;
627 free(attr);
628 return;
629 }
630
631 prev = attr;
632 attr = attr->fNext;
633 }
634}
635
636////////////////////////////////////////////////////////////////////////////////
637/// Free all attributes of the node
638
640{
641 if (xmlnode == 0)
642 return;
643
644 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
645 SXmlAttr_t *attr = node->fAttr;
646 while (attr != 0) {
647 SXmlAttr_t *next = attr->fNext;
648 free(attr);
649 attr = next;
650 }
651 node->fAttr = 0;
652}
653
654////////////////////////////////////////////////////////////////////////////////
655/// return first attribute in the list, namespace (if exists) will be skipped
656
658{
659 if (xmlnode == 0)
660 return 0;
661 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
662
663 SXmlAttr_t *attr = node->fAttr;
664 if ((attr != 0) && (node->fNs == attr))
665 attr = attr->fNext;
666
667 return (XMLAttrPointer_t)attr;
668}
669
670////////////////////////////////////////////////////////////////////////////////
671/// return next attribute in the list
672
674{
675 if (xmlattr == 0)
676 return 0;
677
678 return (XMLAttrPointer_t)((SXmlAttr_t *)xmlattr)->fNext;
679}
680
681////////////////////////////////////////////////////////////////////////////////
682/// return name of the attribute
683
685{
686 if (xmlattr == 0)
687 return 0;
688
689 return SXmlAttr_t::Name(xmlattr);
690}
691
692////////////////////////////////////////////////////////////////////////////////
693/// return value of attribute
694
696{
697 if (xmlattr == 0)
698 return 0;
699
700 const char *attrname = SXmlAttr_t::Name(xmlattr);
701 return attrname + strlen(attrname) + 1;
702}
703
704////////////////////////////////////////////////////////////////////////////////
705/// create new child element for parent node
706
708{
709 int namelen(name != 0 ? strlen(name) : 0);
710
711 SXmlNode_t *node = (SXmlNode_t *)AllocateNode(namelen, parent);
712
713 if (namelen > 0)
714 strncpy(SXmlNode_t::Name(node), name, namelen + 1);
715 else
716 *SXmlNode_t::Name(node) = 0;
717
718 node->fNs = (SXmlAttr_t *)ns;
719 int contlen = (content != 0) ? strlen(content) : 0;
720 if (contlen > 0) {
721 SXmlNode_t *contnode = (SXmlNode_t *)AllocateNode(contlen, node);
722 contnode->fType = kXML_CONTENT; // indicate that we creating content node
723 strncpy(SXmlNode_t::Name(contnode), content, contlen + 1);
724 }
725
726 return (XMLNodePointer_t)node;
727}
728
729////////////////////////////////////////////////////////////////////////////////
730/// create namespace attribute for xmlnode.
731/// namespace attribute will be always the first in list of node attributes
732
733XMLNsPointer_t TXMLEngine::NewNS(XMLNodePointer_t xmlnode, const char *reference, const char *name)
734{
735 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
736 if (name == 0)
737 name = SXmlNode_t::Name(node);
738 int namelen = strlen(name);
739 char *nsname = new char[namelen + 7];
740 snprintf(nsname, namelen + 7, "xmlns:%s", name);
741
742 SXmlAttr_t *first = node->fAttr;
743 node->fAttr = 0;
744
745 SXmlAttr_t *nsattr = (SXmlAttr_t *)NewAttr(xmlnode, 0, nsname, reference);
746
747 node->fAttr = nsattr;
748 nsattr->fNext = first;
749
750 node->fNs = nsattr;
751 delete[] nsname;
752 return (XMLNsPointer_t)nsattr;
753}
754
755////////////////////////////////////////////////////////////////////////////////
756/// return namespace attribute (if exists)
757
759{
760 if (xmlnode == 0)
761 return 0;
762 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
763
764 return (XMLNsPointer_t)node->fNs;
765}
766
767////////////////////////////////////////////////////////////////////////////////
768/// return name id of namespace
769
771{
772 const char *nsname = GetAttrName((XMLAttrPointer_t)ns);
773
774 if ((nsname != 0) && (strncmp(nsname, "xmlns:", 6) == 0))
775 nsname += 6;
776
777 return nsname;
778}
779
780////////////////////////////////////////////////////////////////////////////////
781/// return reference id of namespace
782
784{
786}
787
788////////////////////////////////////////////////////////////////////////////////
789/// add child element to xmlnode
790
792{
793 if ((parent == 0) || (child == 0))
794 return;
795 SXmlNode_t *pnode = (SXmlNode_t *)parent;
796 SXmlNode_t *cnode = (SXmlNode_t *)child;
797
798 if (cnode->fParent)
799 UnlinkNode(child);
800
801 cnode->fParent = pnode;
802 if (pnode->fLastChild == 0) {
803 pnode->fChild = cnode;
804 pnode->fLastChild = cnode;
805 } else {
806 // SXmlNode_t* ch = pnode->fChild;
807 // while (ch->fNext!=0) ch=ch->fNext;
808 pnode->fLastChild->fNext = cnode;
809 pnode->fLastChild = cnode;
810 }
811}
812
813////////////////////////////////////////////////////////////////////////////////
814/// add node as first child
815
817{
818 if ((parent == 0) || (child == 0))
819 return;
820 SXmlNode_t *pnode = (SXmlNode_t *)parent;
821 SXmlNode_t *cnode = (SXmlNode_t *)child;
822
823 if (cnode->fParent)
824 UnlinkNode(child);
825
826 cnode->fParent = pnode;
827
828 cnode->fNext = pnode->fChild;
829 pnode->fChild = cnode;
830
831 if (pnode->fLastChild == 0)
832 pnode->fLastChild = cnode;
833}
834
835////////////////////////////////////////////////////////////////////////////////
836/// Insert new child node after already existing node
837
839{
840 if (afternode == 0) {
841 AddChild(parent, child);
842 return;
843 }
844
845 SXmlNode_t *pnode = (SXmlNode_t *)parent;
846 SXmlNode_t *cnode = (SXmlNode_t *)child;
847 SXmlNode_t *anode = (SXmlNode_t *)afternode;
848
849 if (anode->fParent != pnode) {
850 Error("InsertChildAfter", "Specified afternode is not in childs list of parent node");
851 AddChild(parent, child);
852 return;
853 }
854
855 if (cnode->fParent)
856 UnlinkNode(child);
857
858 cnode->fParent = pnode;
859
860 cnode->fNext = anode->fNext;
861 anode->fNext = cnode;
862
863 if (pnode->fLastChild == anode)
864 pnode->fLastChild = cnode;
865}
866
867////////////////////////////////////////////////////////////////////////////////
868/// Adds comment line to the node
869
870Bool_t TXMLEngine::AddComment(XMLNodePointer_t xmlnode, const char *comment)
871{
872 if ((xmlnode == 0) || (comment == 0))
873 return kFALSE;
874
875 int commentlen = strlen(comment);
876
877 SXmlNode_t *node = (SXmlNode_t *)AllocateNode(commentlen, xmlnode);
878 node->fType = kXML_COMMENT;
879 strncpy(SXmlNode_t::Name(node), comment, commentlen + 1);
880
881 return kTRUE;
882}
883
884////////////////////////////////////////////////////////////////////////////////
885/// add comment line to the top of the document
886
888{
889 if (xmldoc == 0)
890 return kFALSE;
891
892 XMLNodePointer_t rootnode = DocGetRootElement(xmldoc);
893 UnlinkNode(rootnode);
894
895 Bool_t res = AddComment(((SXmlDoc_t *)xmldoc)->fRootNode, comment);
896
897 AddChild((XMLNodePointer_t)((SXmlDoc_t *)xmldoc)->fRootNode, rootnode);
898
899 return res;
900}
901
902////////////////////////////////////////////////////////////////////////////////
903/// Add just line into xml file
904/// Line should has correct xml syntax that later it can be decoded by xml parser
905/// For instance, it can be comment or processing instructions
906
908{
909 if ((xmlnode == 0) || (line == 0))
910 return kFALSE;
911
912 int linelen = strlen(line);
913 SXmlNode_t *node = (SXmlNode_t *)AllocateNode(linelen, xmlnode);
914 node->fType = kXML_RAWLINE;
915 strncpy(SXmlNode_t::Name(node), line, linelen + 1);
916
917 return kTRUE;
918}
919
920////////////////////////////////////////////////////////////////////////////////
921/// Add just line on the top of xml document
922/// Line should has correct xml syntax that later it can be decoded by xml parser
923
925{
926 XMLNodePointer_t rootnode = DocGetRootElement(xmldoc);
927 UnlinkNode(rootnode);
928
929 Bool_t res = AddRawLine(((SXmlDoc_t *)xmldoc)->fRootNode, line);
930
931 AddChild((XMLNodePointer_t)((SXmlDoc_t *)xmldoc)->fRootNode, rootnode);
932
933 return res;
934}
935
936////////////////////////////////////////////////////////////////////////////////
937/// Adds style sheet definition to the specified node
938/// Creates <?xml-stylesheet alternate="yes" title="compact" href="small-base.css" type="text/css"?>
939/// Attributes href and type must be supplied,
940/// other attributes: title, alternate, media, charset are optional
941/// if alternate==0, attribute alternate="no" will be created,
942/// if alternate>0, attribute alternate="yes"
943/// if alternate<0, attribute will not be created
944
945Bool_t TXMLEngine::AddStyleSheet(XMLNodePointer_t xmlnode, const char *href, const char *type, const char *title,
946 int alternate, const char *media, const char *charset)
947{
948 if ((xmlnode == 0) || (href == 0) || (type == 0))
949 return kFALSE;
950
951 const char *nodename = "xml-stylesheet";
952 int nodenamelen = strlen(nodename);
953
954 SXmlNode_t *node = (SXmlNode_t *)AllocateNode(nodenamelen, xmlnode);
955 node->fType = kXML_PI_NODE;
956 strncpy(SXmlNode_t::Name(node), nodename, nodenamelen + 1);
957
958 if (alternate >= 0)
959 NewAttr(node, 0, "alternate", (alternate > 0) ? "yes" : "no");
960
961 if (title != 0)
962 NewAttr(node, 0, "title", title);
963
964 NewAttr(node, 0, "href", href);
965 NewAttr(node, 0, "type", type);
966
967 if (media != 0)
968 NewAttr(node, 0, "media", media);
969 if (charset != 0)
970 NewAttr(node, 0, "charset", charset);
971
972 return kTRUE;
973}
974
975////////////////////////////////////////////////////////////////////////////////
976/// Add style sheet definition on the top of document
977
978Bool_t TXMLEngine::AddDocStyleSheet(XMLDocPointer_t xmldoc, const char *href, const char *type, const char *title,
979 int alternate, const char *media, const char *charset)
980{
981 if (xmldoc == 0)
982 return kFALSE;
983
984 XMLNodePointer_t rootnode = DocGetRootElement(xmldoc);
985 UnlinkNode(rootnode);
986
987 Bool_t res = AddStyleSheet(((SXmlDoc_t *)xmldoc)->fRootNode, href, type, title, alternate, media, charset);
988
989 AddChild((XMLNodePointer_t)((SXmlDoc_t *)xmldoc)->fRootNode, rootnode);
990
991 return res;
992}
993
994////////////////////////////////////////////////////////////////////////////////
995/// unlink (detach) xmlnode from parent
996
998{
999 if (xmlnode == 0)
1000 return;
1001
1002 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
1003 SXmlNode_t *parent = node->fParent;
1004
1005 if (parent == 0)
1006 return;
1007
1008 if (parent->fChild == node) {
1009 parent->fChild = node->fNext;
1010 if (parent->fLastChild == node)
1011 parent->fLastChild = node->fNext;
1012 } else {
1013 SXmlNode_t *ch = parent->fChild;
1014 while (ch->fNext != node)
1015 ch = ch->fNext;
1016 ch->fNext = node->fNext;
1017 if (parent->fLastChild == node)
1018 parent->fLastChild = ch;
1019 }
1020
1021 node->fParent = 0;
1022 node->fNext = 0;
1023}
1024
1025////////////////////////////////////////////////////////////////////////////////
1026/// release all memory, allocated from this node and
1027/// destroys node itself
1028
1030{
1031 if (xmlnode == 0)
1032 return;
1033 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
1034
1035 SXmlNode_t *child = node->fChild;
1036 while (child != 0) {
1037 SXmlNode_t *next = child->fNext;
1038 FreeNode((XMLNodePointer_t)child);
1039 child = next;
1040 }
1041
1042 SXmlAttr_t *attr = node->fAttr;
1043 while (attr != 0) {
1044 SXmlAttr_t *next = attr->fNext;
1045 // fNumNodes--;
1046 free(attr);
1047 attr = next;
1048 }
1049
1050 free(node);
1051
1052 // fNumNodes--;
1053}
1054
1055////////////////////////////////////////////////////////////////////////////////
1056/// combined operation. Unlink node and free used memory
1057
1059{
1060 UnlinkNode(xmlnode);
1061 FreeNode(xmlnode);
1062}
1063
1064////////////////////////////////////////////////////////////////////////////////
1065/// returns name of xmlnode
1066
1068{
1069 return xmlnode == 0 ? 0 : SXmlNode_t::Name(xmlnode);
1070}
1071
1072////////////////////////////////////////////////////////////////////////////////
1073/// get contents (if any) of xmlnode
1074
1076{
1077 if (xmlnode == 0)
1078 return 0;
1079 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
1080 if (node->fChild == 0)
1081 return 0;
1082
1083 if (node->fChild->fType != kXML_CONTENT)
1084 return 0;
1085
1086 return SXmlNode_t::Name(node->fChild);
1087}
1088
1089////////////////////////////////////////////////////////////////////////////////
1090/// set content of the xmlnode
1091/// if old node content was exists, it will be replaced
1092
1093void TXMLEngine::SetNodeContent(XMLNodePointer_t xmlnode, const char *content, Int_t len)
1094{
1095 if (xmlnode == 0)
1096 return;
1097 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
1098 if ((node->fChild != 0) && (node->fChild->fType == kXML_CONTENT))
1099 UnlinkFreeNode((XMLNodePointer_t)node->fChild);
1100
1101 if (content == 0)
1102 return;
1103 if (len <= 0)
1104 len = strlen(content);
1105
1106 SXmlNode_t *contnode = (SXmlNode_t *)AllocateNode(len, 0);
1107 char *nameptr = SXmlNode_t::Name(contnode);
1108 contnode->fType = kXML_CONTENT;
1109 strncpy(nameptr, content, len);
1110 nameptr += len;
1111 *nameptr = 0; // here we add padding 0 to get normal string
1112
1113 AddChildFirst(xmlnode, (XMLNodePointer_t)contnode);
1114}
1115
1116////////////////////////////////////////////////////////////////////////////////
1117/// add new content of the xmlnode
1118/// old content will be preserved, one could mix content with child nodes
1119
1120void TXMLEngine::AddNodeContent(XMLNodePointer_t xmlnode, const char *content, Int_t len)
1121{
1122 if ((xmlnode == 0) || (content == 0))
1123 return;
1124 if (len <= 0)
1125 len = strlen(content);
1126
1127 SXmlNode_t *contnode = (SXmlNode_t *)AllocateNode(len, xmlnode);
1128 char *nameptr = SXmlNode_t::Name(contnode);
1129 contnode->fType = kXML_CONTENT;
1130 strncpy(nameptr, content, len);
1131 nameptr += len;
1132 *nameptr = 0; // here we add padding 0 to get normal string
1133}
1134
1135////////////////////////////////////////////////////////////////////////////////
1136/// returns first child of xmlnode
1137
1139{
1140 XMLNodePointer_t res = xmlnode == 0 ? 0 : ((SXmlNode_t *)xmlnode)->fChild;
1141 // skip content(s) node, if specified
1142 if (realnode && (res != 0) && (((SXmlNode_t *)res)->fType != kXML_NODE))
1143 ShiftToNext(res, kTRUE);
1144 return res;
1145}
1146
1147////////////////////////////////////////////////////////////////////////////////
1148/// returns parent of xmlnode
1149
1151{
1152 return xmlnode == 0 ? 0 : (XMLNodePointer_t)((SXmlNode_t *)xmlnode)->fParent;
1153}
1154
1155////////////////////////////////////////////////////////////////////////////////
1156/// return next to xmlnode node
1157/// if realnode==kTRUE, any special nodes in between will be skipped
1158
1160{
1161 do {
1162 xmlnode = xmlnode == 0 ? 0 : (XMLNodePointer_t)((SXmlNode_t *)xmlnode)->fNext;
1163 if ((xmlnode == 0) || !realnode)
1164 return xmlnode;
1165 } while (((SXmlNode_t *)xmlnode)->fType != kXML_NODE);
1166
1167 return xmlnode;
1168}
1169
1170////////////////////////////////////////////////////////////////////////////////
1171/// shifts specified node to next
1172/// if realnode==kTRUE, any special nodes in between will be skipped
1173
1175{
1176 do {
1177 xmlnode = xmlnode == 0 ? 0 : (XMLNodePointer_t)((SXmlNode_t *)xmlnode)->fNext;
1178 if ((xmlnode == 0) || !realnode)
1179 return;
1180 } while (((SXmlNode_t *)xmlnode)->fType != kXML_NODE);
1181}
1182
1183////////////////////////////////////////////////////////////////////////////////
1184/// return kTRUE is this is normal xmlnode
1185
1187{
1188 return xmlnode == 0 ? kFALSE : (((SXmlNode_t *)xmlnode)->fType == kXML_NODE);
1189}
1190
1191////////////////////////////////////////////////////////////////////////////////
1192/// return kTRUE is this is node with special data like comments to data processing instructions
1193
1195{
1196 return xmlnode == 0 ? kTRUE : (((SXmlNode_t *)xmlnode)->fType != kXML_NODE);
1197}
1198
1199////////////////////////////////////////////////////////////////////////////////
1200/// return kTRUE is this is special node with content
1201
1203{
1204 return xmlnode == 0 ? kFALSE : (((SXmlNode_t *)xmlnode)->fType == kXML_CONTENT);
1205}
1206
1207////////////////////////////////////////////////////////////////////////////////
1208/// return kTRUE is this is special node with content
1209
1211{
1212 return xmlnode == 0 ? kFALSE : (((SXmlNode_t *)xmlnode)->fType == kXML_COMMENT);
1213}
1214
1215////////////////////////////////////////////////////////////////////////////////
1216/// Skip all current empty nodes and locate on first "true" node
1217
1219{
1220 if (IsEmptyNode(xmlnode))
1221 ShiftToNext(xmlnode);
1222}
1223
1224////////////////////////////////////////////////////////////////////////////////
1225/// remove all children node from xmlnode
1226
1228{
1229 if (xmlnode == 0)
1230 return;
1231 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
1232
1233 SXmlNode_t *child = node->fChild;
1234 while (child != 0) {
1235 SXmlNode_t *next = child->fNext;
1236 FreeNode((XMLNodePointer_t)child);
1237 child = next;
1238 }
1239
1240 node->fChild = 0;
1241 node->fLastChild = 0;
1242}
1243
1244////////////////////////////////////////////////////////////////////////////////
1245/// creates new xml document with provided version
1246
1248{
1249 SXmlDoc_t *doc = new SXmlDoc_t;
1250 doc->fRootNode = (SXmlNode_t *)NewChild(0, 0, "??DummyTopNode??", 0);
1251
1252 if (version != 0) {
1253 XMLNodePointer_t vernode = NewChild((XMLNodePointer_t)doc->fRootNode, 0, "xml");
1254 ((SXmlNode_t *)vernode)->fType = kXML_PI_NODE;
1255 NewAttr(vernode, 0, "version", version);
1256 }
1257
1258 doc->fDtdName = 0;
1259 doc->fDtdRoot = 0;
1260 return (XMLDocPointer_t)doc;
1261}
1262
1263////////////////////////////////////////////////////////////////////////////////
1264/// assigns dtd filename to document
1265
1266void TXMLEngine::AssignDtd(XMLDocPointer_t xmldoc, const char *dtdname, const char *rootname)
1267{
1268 if (xmldoc == 0)
1269 return;
1270 SXmlDoc_t *doc = (SXmlDoc_t *)xmldoc;
1271 delete[] doc->fDtdName;
1272 doc->fDtdName = Makestr(dtdname);
1273 delete[] doc->fDtdRoot;
1274 doc->fDtdRoot = Makestr(rootname);
1275}
1276
1277////////////////////////////////////////////////////////////////////////////////
1278/// frees allocated document data and deletes document itself
1279
1281{
1282 if (xmldoc == 0)
1283 return;
1284 SXmlDoc_t *doc = (SXmlDoc_t *)xmldoc;
1285 FreeNode((XMLNodePointer_t)doc->fRootNode);
1286 delete[] doc->fDtdName;
1287 delete[] doc->fDtdRoot;
1288 delete doc;
1289}
1290
1291////////////////////////////////////////////////////////////////////////////////
1292/// store document content to file
1293/// if layout<=0, no any spaces or newlines will be placed between
1294/// xmlnodes. Xml file will have minimum size, but non-readable structure
1295/// if (layout>0) each node will be started from new line,
1296/// and number of spaces will correspond to structure depth.
1297
1298void TXMLEngine::SaveDoc(XMLDocPointer_t xmldoc, const char *filename, Int_t layout)
1299{
1300 if (xmldoc == 0)
1301 return;
1302
1303 SXmlDoc_t *doc = (SXmlDoc_t *)xmldoc;
1304
1305 TXMLOutputStream out(filename, 100000);
1306
1307 XMLNodePointer_t child = GetChild((XMLNodePointer_t)doc->fRootNode, kFALSE);
1308
1309 do {
1310 SaveNode(child, &out, layout, 0);
1311 ShiftToNext(child, kFALSE);
1312 } while (child != 0);
1313}
1314
1315////////////////////////////////////////////////////////////////////////////////
1316/// set main (root) node for document
1317
1319{
1320 if (xmldoc == 0)
1321 return;
1322
1323 FreeNode(DocGetRootElement(xmldoc));
1324
1325 AddChild((XMLNodePointer_t)((SXmlDoc_t *)xmldoc)->fRootNode, xmlnode);
1326}
1327
1328////////////////////////////////////////////////////////////////////////////////
1329/// returns root node of document
1330
1332{
1333 if (xmldoc == 0)
1334 return 0;
1335
1336 XMLNodePointer_t xmlnode = (XMLNodePointer_t)((SXmlDoc_t *)xmldoc)->fRootNode;
1337
1338 // typically first child of XML document is version
1339 // therefore just skip it when returning root node of document
1340 return GetChild(xmlnode, kTRUE);
1341}
1342
1343////////////////////////////////////////////////////////////////////////////////
1344/// Parses content of file and tries to produce xml structures.
1345/// The maxbuf argument specifies the max size of the XML file to be
1346/// parsed. The default value is 100000.
1347
1348XMLDocPointer_t TXMLEngine::ParseFile(const char *filename, Int_t maxbuf)
1349{
1350 if ((filename == 0) || (strlen(filename) == 0))
1351 return 0;
1352 if (maxbuf < 100000)
1353 maxbuf = 100000;
1354 TXMLInputStream inp(true, filename, maxbuf);
1355 return ParseStream(&inp);
1356}
1357
1358////////////////////////////////////////////////////////////////////////////////
1359/// parses content of string and tries to produce xml structures
1360
1362{
1363 if ((xmlstring == 0) || (strlen(xmlstring) == 0))
1364 return 0;
1365 TXMLInputStream inp(false, xmlstring, 100000);
1366 return ParseStream(&inp);
1367}
1368
1369////////////////////////////////////////////////////////////////////////////////
1370/// parses content of the stream and tries to produce xml structures
1371
1373{
1374 if (inp == 0)
1375 return 0;
1376
1377 XMLDocPointer_t xmldoc = NewDoc(0);
1378
1379 Bool_t success = false;
1380
1381 Int_t resvalue = 0;
1382
1383 do {
1384 ReadNode(((SXmlDoc_t *)xmldoc)->fRootNode, inp, resvalue);
1385
1386 if (resvalue != 2)
1387 break;
1388
1389 // coverity[unchecked_value] at this place result of SkipSpaces() doesn't matter - either file is finished (false)
1390 // or there is some more nodes to analyse (true)
1391 if (!inp->EndOfStream())
1392 inp->SkipSpaces();
1393
1394 if (inp->EndOfStream()) {
1395 success = true;
1396 break;
1397 }
1398 } while (true);
1399
1400 if (!success) {
1401 DisplayError(resvalue, inp->CurrentLine());
1402 FreeDoc(xmldoc);
1403 return 0;
1404 }
1405
1406 return xmldoc;
1407}
1408
1409////////////////////////////////////////////////////////////////////////////////
1410/// check that first node is xml processing instruction with correct xml version number
1411
1413{
1414 if (xmldoc == 0)
1415 return kFALSE;
1416
1417 XMLNodePointer_t vernode = GetChild((XMLNodePointer_t)((SXmlDoc_t *)xmldoc)->fRootNode, kFALSE);
1418 if (vernode == 0)
1419 return kFALSE;
1420
1421 if (((SXmlNode_t *)vernode)->fType != kXML_PI_NODE)
1422 return kFALSE;
1423 if (strcmp(GetNodeName(vernode), "xml") != 0)
1424 return kFALSE;
1425
1426 const char *value = GetAttr(vernode, "version");
1427 if (value == 0)
1428 return kFALSE;
1429 if (version == 0)
1430 version = "1.0";
1431
1432 return strcmp(version, value) == 0;
1433}
1434
1435////////////////////////////////////////////////////////////////////////////////
1436/// convert single xmlnode (and its child node) to string
1437/// if layout<=0, no any spaces or newlines will be placed between
1438/// xmlnodes. Xml file will have minimum size, but non-readable structure
1439/// if (layout>0) each node will be started from new line,
1440/// and number of spaces will correspond to structure depth.
1441
1443{
1444 if ((res == 0) || (xmlnode == 0))
1445 return;
1446
1447 TXMLOutputStream out(res, 10000);
1448
1449 SaveNode(xmlnode, &out, layout, 0);
1450}
1451
1452////////////////////////////////////////////////////////////////////////////////
1453/// read single xmlnode from provided string
1454
1456{
1457 if (src == 0)
1458 return 0;
1459
1460 TXMLInputStream inp(false, src, 10000);
1461
1462 Int_t resvalue;
1463
1464 XMLNodePointer_t xmlnode = ReadNode(0, &inp, resvalue);
1465
1466 if (resvalue <= 0) {
1467 DisplayError(resvalue, inp.CurrentLine());
1468 FreeNode(xmlnode);
1469 return 0;
1470 }
1471
1472 return xmlnode;
1473}
1474
1475////////////////////////////////////////////////////////////////////////////////
1476/// creates char* variable with copy of provided string
1477
1478char *TXMLEngine::Makestr(const char *str)
1479{
1480 if (str == 0)
1481 return 0;
1482 int len = strlen(str);
1483 if (len == 0)
1484 return 0;
1485 char *res = new char[len + 1];
1486 strncpy(res, str, len + 1);
1487 return res;
1488}
1489
1490////////////////////////////////////////////////////////////////////////////////
1491/// creates char* variable with copy of len symbols from provided string
1492
1493char *TXMLEngine::Makenstr(const char *str, int len)
1494{
1495 if ((str == 0) || (len == 0))
1496 return 0;
1497 char *res = new char[len + 1];
1498 strncpy(res, str, len);
1499 *(res + len) = 0;
1500 return res;
1501}
1502
1503////////////////////////////////////////////////////////////////////////////////
1504/// Allocates new xml node with specified name length
1505
1507{
1508 // fNumNodes++;
1509
1510 SXmlNode_t *node = (SXmlNode_t *)malloc(sizeof(SXmlNode_t) + namelen + 1);
1511
1512 node->fType = kXML_NODE;
1513 node->fParent = 0;
1514 node->fNs = 0;
1515 node->fAttr = 0;
1516 node->fChild = 0;
1517 node->fLastChild = 0;
1518 node->fNext = 0;
1519
1520 if (parent != 0)
1521 AddChild(parent, (XMLNodePointer_t)node);
1522
1523 return (XMLNodePointer_t)node;
1524}
1525
1526////////////////////////////////////////////////////////////////////////////////
1527/// Allocate new attribute with specified name length and value length
1528
1530{
1531 // fNumNodes++;
1532
1533 SXmlAttr_t *attr = (SXmlAttr_t *)malloc(sizeof(SXmlAttr_t) + namelen + 1 + valuelen + 1);
1534
1535 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
1536
1537 attr->fNext = 0;
1538
1539 if (node->fAttr == 0)
1540 node->fAttr = attr;
1541 else {
1542 SXmlAttr_t *d = node->fAttr;
1543 while (d->fNext != 0)
1544 d = d->fNext;
1545 d->fNext = attr;
1546 }
1547
1548 return (XMLAttrPointer_t)attr;
1549}
1550
1551////////////////////////////////////////////////////////////////////////////////
1552/// define if namespace of that name exists for xmlnode
1553
1555{
1556 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
1557 while (node != 0) {
1558 if (node->fNs != 0) {
1559 const char *nsname = SXmlAttr_t::Name(node->fNs) + 6;
1560 if (strcmp(nsname, name) == 0)
1561 return node->fNs;
1562 }
1563 node = node->fParent;
1564 }
1565 return 0;
1566}
1567
1568////////////////////////////////////////////////////////////////////////////////
1569/// removes namespace extension of nodename
1570
1572{
1573 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
1574 if (node == 0)
1575 return;
1576 char *colon = strchr(SXmlNode_t::Name(node), ':');
1577 if (colon == 0)
1578 return;
1579
1580 char *copyname = SXmlNode_t::Name(node);
1581
1582 while (*colon != 0)
1583 *(copyname++) = *(++colon);
1584}
1585
1586////////////////////////////////////////////////////////////////////////////////
1587/// unpack special symbols, used in xml syntax to code characters
1588/// these symbols: '<' - &lt, '>' - &gt, '&' - &amp, '"' - &quot, ''' - &apos
1589
1590void TXMLEngine::UnpackSpecialCharacters(char *target, const char *source, int srclen)
1591{
1592 while (srclen > 0) {
1593 if (*source == '&') {
1594 if ((srclen > 3) && (*(source + 1) == 'l') && (*(source + 2) == 't') && (*(source + 3) == ';')) {
1595 *target++ = '<';
1596 source += 4;
1597 srclen -= 4;
1598 } else if ((srclen > 3) && (*(source + 1) == 'g') && (*(source + 2) == 't') && (*(source + 3) == ';')) {
1599 *target++ = '>';
1600 source += 4;
1601 srclen -= 4;
1602 } else if ((srclen > 4) && (*(source + 1) == 'a') && (*(source + 2) == 'm') && (*(source + 3) == 'p') &&
1603 (*(source + 4) == ';')) {
1604 *target++ = '&';
1605 source += 5;
1606 srclen -= 5;
1607 } else if ((srclen > 5) && (*(source + 1) == 'q') && (*(source + 2) == 'u') && (*(source + 3) == 'o') &&
1608 (*(source + 4) == 't') && (*(source + 5) == ';')) {
1609 *target++ = '\"';
1610 source += 6;
1611 srclen -= 6;
1612 } else if ((srclen > 5) && (*(source + 1) == 'a') && (*(source + 2) == 'p') && (*(source + 3) == 'o') &&
1613 (*(source + 4) == 's') && (*(source + 5) == ';')) {
1614 *target++ = '\'';
1615 source += 6;
1616 srclen -= 6;
1617 } else {
1618 *target++ = *source++;
1619 srclen--;
1620 }
1621 } else {
1622 *target++ = *source++;
1623 srclen--;
1624 }
1625 }
1626 *target = 0;
1627}
1628
1629////////////////////////////////////////////////////////////////////////////////
1630/// output value to output stream
1631/// if symbols '<' '&' '>' '"' ''' appears in the string, they
1632/// will be encoded to appropriate xml symbols: &lt, &amp, &gt, &quot, &apos
1633
1634void TXMLEngine::OutputValue(char *value, TXMLOutputStream *out)
1635{
1636 if (value == 0)
1637 return;
1638
1639 char *last = value;
1640 char *find = 0;
1641 while ((find = strpbrk(last, "<&>\"")) != 0) {
1642 char symb = *find;
1643 *find = 0;
1644 out->Write(last);
1645 *find = symb;
1646 last = find + 1;
1647 if (symb == '<')
1648 out->Write("&lt;");
1649 else if (symb == '>')
1650 out->Write("&gt;");
1651 else if (symb == '&')
1652 out->Write("&amp;");
1653 else if (symb == '\'')
1654 out->Write("&apos;");
1655 else
1656 out->Write("&quot;");
1657 }
1658 if (*last != 0)
1659 out->Write(last);
1660}
1661
1662////////////////////////////////////////////////////////////////////////////////
1663/// stream data of xmlnode to output
1664
1665void TXMLEngine::SaveNode(XMLNodePointer_t xmlnode, TXMLOutputStream *out, Int_t layout, Int_t level)
1666{
1667 if (xmlnode == 0)
1668 return;
1669 SXmlNode_t *node = (SXmlNode_t *)xmlnode;
1670
1671 Bool_t issingleline = (node->fChild == 0);
1672
1673 if (layout > 0)
1674 out->Put(' ', level);
1675
1676 if (node->fType == kXML_COMMENT) {
1677 out->Write("<!--");
1678 out->Write(SXmlNode_t::Name(node));
1679 out->Write("-->");
1680 if (layout > 0)
1681 out->Put('\n');
1682 return;
1683 } else if (node->fType == kXML_RAWLINE) {
1684 out->Write(SXmlNode_t::Name(node));
1685 if (layout > 0)
1686 out->Put('\n');
1687 return;
1688 } else if (node->fType == kXML_CONTENT) {
1689 out->Write(SXmlNode_t::Name(node));
1690 if (layout > 0)
1691 out->Put('\n');
1692 return;
1693 }
1694
1695 out->Put('<');
1696 if (node->fType == kXML_PI_NODE)
1697 out->Put('?');
1698
1699 // we suppose that ns is always first attribute
1700 if ((node->fNs != 0) && (node->fNs != node->fAttr)) {
1701 out->Write(SXmlAttr_t::Name(node->fNs) + 6);
1702 out->Put(':');
1703 }
1704 out->Write(SXmlNode_t::Name(node));
1705
1706 SXmlAttr_t *attr = node->fAttr;
1707 while (attr != 0) {
1708 out->Put(' ');
1709 char *attrname = SXmlAttr_t::Name(attr);
1710 out->Write(attrname);
1711 out->Write("=\"");
1712 attrname += strlen(attrname) + 1;
1713 OutputValue(attrname, out);
1714 out->Put('\"');
1715 attr = attr->fNext;
1716 }
1717
1718 // if single line, close node with "/>" and return
1719 if (issingleline) {
1720 if (node->fType == kXML_PI_NODE)
1721 out->Write("?>");
1722 else
1723 out->Write("/>");
1724 if (layout > 0)
1725 out->Put('\n');
1726 return;
1727 }
1728
1729 out->Put('>');
1730
1731 SXmlNode_t *child = node->fChild;
1732
1733 if ((child != 0) && (child->fType == kXML_CONTENT) && (child->fNext == 0)) {
1734 // special case when single content node is exists
1735 out->Write(SXmlNode_t::Name(child));
1736 } else {
1737 if (layout > 0)
1738 out->Put('\n');
1739 while (child != 0) {
1740 SaveNode((XMLNodePointer_t)child, out, layout, level + 2);
1741 child = child->fNext;
1742 }
1743 // add starting spaces before closing node
1744 if (layout > 0)
1745 out->Put(' ', level);
1746 }
1747
1748 out->Write("</");
1749 // we suppose that ns is always first attribute
1750 if ((node->fNs != 0) && (node->fNs != node->fAttr)) {
1751 out->Write(SXmlAttr_t::Name(node->fNs) + 6);
1752 out->Put(':');
1753 }
1754 out->Write(SXmlNode_t::Name(node));
1755 out->Put('>');
1756 if (layout > 0)
1757 out->Put('\n');
1758}
1759
1760////////////////////////////////////////////////////////////////////////////////
1761/// Tries to construct xml node from input stream. Node should be
1762/// child of xmlparent node or it can be closing tag of xmlparent.
1763/// resvalue <= 0 if error
1764/// resvalue == 1 if this is endnode of parent
1765/// resvalue == 2 if this is child
1766
1767XMLNodePointer_t TXMLEngine::ReadNode(XMLNodePointer_t xmlparent, TXMLInputStream *inp, Int_t &resvalue)
1768{
1769 resvalue = 0;
1770
1771 if (inp == 0)
1772 return 0;
1773 if (!inp->SkipSpaces()) {
1774 resvalue = -1;
1775 return 0;
1776 }
1777 SXmlNode_t *parent = (SXmlNode_t *)xmlparent;
1778
1779 SXmlNode_t *node = 0;
1780
1781 // process comments before we start to analyse any node symbols
1782 while (inp->CheckFor("<!--")) {
1783 Int_t commentlen = inp->SearchFor("-->");
1784 if (commentlen <= 0) {
1785 resvalue = -10;
1786 return 0;
1787 }
1788
1789 if (!fSkipComments) {
1790 node = (SXmlNode_t *)AllocateNode(commentlen, xmlparent);
1791 char *nameptr = SXmlNode_t::Name(node);
1792 node->fType = kXML_COMMENT;
1793 strncpy(nameptr, inp->fCurrent, commentlen); // here copy only content, there is no padding 0 at the end
1794 nameptr += commentlen;
1795 *nameptr = 0; // here we add padding 0 to get normal string
1796 }
1797
1798 if (!inp->ShiftCurrent(commentlen + 3)) {
1799 resvalue = -1;
1800 return node;
1801 }
1802 if (!inp->SkipSpaces() && !inp->EndOfStream()) {
1803 resvalue = -1;
1804 return node;
1805 }
1806
1807 resvalue = 2;
1808 return node;
1809 }
1810
1811 if (*inp->fCurrent != '<') {
1812 // here should be reading of element content
1813 // now one can have content at any place of the node, also after childs
1814 if (parent == 0) {
1815 resvalue = -2;
1816 return 0;
1817 }
1818 int contlen = inp->LocateContent();
1819 if (contlen < 0)
1820 return 0;
1821
1822 SXmlNode_t *contnode = (SXmlNode_t *)AllocateNode(contlen, xmlparent);
1823 contnode->fType = kXML_CONTENT;
1824 char *contptr = SXmlNode_t::Name(contnode);
1825 UnpackSpecialCharacters(contptr, inp->fCurrent, contlen);
1826 if (!inp->ShiftCurrent(contlen))
1827 return 0;
1828
1829 if (inp->NumEntities() <= 0) {
1830 resvalue = 2;
1831 return contnode;
1832 }
1833
1834 // analyze content on possible includes only when ENTITY was specified for document
1835
1836 const char *beg(0), *lastentity(0), *curr(contptr);
1837
1838 while (*curr != 0) {
1839 if ((beg == 0) && (*curr == '&'))
1840 beg = curr;
1841 if ((beg == 0) || (*curr != ';')) {
1842 curr++;
1843 continue;
1844 }
1845
1846 TXMLEntity *entity = inp->FindEntity(beg + 1, curr - beg - 1);
1847
1848 if (entity != 0) {
1849
1850 if (lastentity == 0) {
1851 lastentity = contptr;
1852 UnlinkNode(contnode);
1853 }
1854
1855 if (lastentity != beg)
1856 AddNodeContent(xmlparent, lastentity, beg - lastentity);
1857
1858 if (entity->IsSystem()) {
1859 XMLDocPointer_t entitydoc = ParseFile(entity->GetTitle());
1860 if (entitydoc == 0) {
1861 resvalue = -14;
1862 return contnode;
1863 }
1864
1865 XMLNodePointer_t topnode = DocGetRootElement(entitydoc);
1866
1867 while (topnode != 0) {
1868 XMLNodePointer_t currnode = topnode;
1869 ShiftToNext(topnode, false);
1870 UnlinkNode(currnode);
1871 AddChild(xmlparent, currnode);
1872 }
1873 } else {
1874 AddNodeContent(xmlparent, entity->GetTitle());
1875 }
1876 }
1877
1878 beg = 0;
1879 curr++;
1880
1881 lastentity = curr;
1882 }
1883
1884 if (lastentity != 0) {
1885 // add rest part of the content
1886 if (strlen(lastentity) > 0)
1887 AddNodeContent(xmlparent, lastentity);
1888 // do not forget to cleanup content node
1889 FreeNode(contnode);
1890 contnode = 0;
1891 }
1892
1893 resvalue = 2;
1894 return contnode;
1895 } else {
1896 // skip "<" symbol
1897 if (!inp->ShiftCurrent())
1898 return 0;
1899 }
1900
1901 if (*inp->fCurrent == '/') {
1902 // this is a starting of closing node
1903 if (!inp->ShiftCurrent())
1904 return 0;
1905 if (!inp->SkipSpaces())
1906 return 0;
1907 Int_t len = inp->LocateIdentifier();
1908 if (len <= 0) {
1909 resvalue = -3;
1910 return 0;
1911 }
1912
1913 if (parent == 0) {
1914 resvalue = -4;
1915 return 0;
1916 }
1917
1918 if (strncmp(SXmlNode_t::Name(parent), inp->fCurrent, len) != 0) {
1919 resvalue = -5;
1920 return 0;
1921 }
1922
1923 if (!inp->ShiftCurrent(len))
1924 return 0;
1925
1926 if (!inp->SkipSpaces())
1927 return 0;
1928 if (*inp->fCurrent != '>')
1929 return 0;
1930 if (!inp->ShiftCurrent())
1931 return 0;
1932
1933 if (parent->fNs != 0)
1935
1936 inp->SkipSpaces(kTRUE); // locate start of next string
1937 resvalue = 1;
1938 return 0;
1939 }
1940
1941 if (*inp->fCurrent == '!') {
1942 // this is start of DTD reading, only limited number of features are supported
1943 if (!inp->ShiftCurrent())
1944 return 0;
1945 if (!inp->CheckFor("DOCTYPE")) {
1946 resvalue = -12;
1947 return 0;
1948 }
1949 if (!inp->SkipSpaces()) {
1950 resvalue = -13;
1951 return 0;
1952 }
1953
1954 // now skip name of the root element - it is not verified at all
1955 Int_t len = inp->LocateIdentifier();
1956 if (len <= 0) {
1957 resvalue = -13;
1958 return 0;
1959 }
1960 if (!inp->ShiftCurrent(len)) {
1961 resvalue = -13;
1962 return 0;
1963 }
1964 if (!inp->SkipSpaces()) {
1965 resvalue = -13;
1966 return 0;
1967 }
1968
1969 // this is start of reading ENTITIES
1970 if (inp->CheckFor("[")) {
1971 if (!inp->SkipSpaces())
1972 return 0;
1973 while (true) {
1974 if (inp->CheckFor("<!ENTITY")) {
1975 // process ENTITY from DTD
1976 if (!inp->SkipSpaces()) {
1977 resvalue = -13;
1978 return 0;
1979 }
1980 Int_t namelen = inp->LocateIdentifier();
1981 if (namelen <= 0) {
1982 resvalue = -13;
1983 return 0;
1984 }
1985 TString entity_name(inp->fCurrent, namelen);
1986 if (!inp->ShiftCurrent(namelen)) {
1987 resvalue = -13;
1988 return 0;
1989 }
1990 if (!inp->SkipSpaces()) {
1991 resvalue = -13;
1992 return 0;
1993 }
1994 Bool_t is_system = kFALSE;
1995 if (inp->CheckFor("SYSTEM")) {
1996 if (!inp->SkipSpaces()) {
1997 resvalue = -13;
1998 return 0;
1999 }
2000 is_system = kTRUE;
2001 }
2002
2003 Int_t valuelen = inp->LocateValue(0, false);
2004 if (valuelen < 2) {
2005 resvalue = -13;
2006 return 0;
2007 }
2008
2009 TString entity_value(inp->fCurrent + 1, valuelen - 2);
2010
2011 if (!inp->ShiftCurrent(valuelen)) {
2012 resvalue = -13;
2013 return 0;
2014 }
2015 inp->SkipSpaces();
2016 if (*inp->fCurrent != '>') {
2017 resvalue = -13;
2018 return 0;
2019 }
2020 if (!inp->ShiftCurrent()) {
2021 resvalue = -13;
2022 return 0;
2023 }
2024 inp->SkipSpaces();
2025
2026 inp->AddEntity(new TXMLEntity(entity_name, entity_value, is_system));
2027 continue;
2028 }
2029
2030 if (inp->CheckFor("<!ELEMENT")) {
2031 // process ELEMENT from DTD - dummy at the moment
2032 if (!inp->SkipSpaces()) {
2033 resvalue = -13;
2034 return 0;
2035 }
2036 Int_t namelen = inp->LocateIdentifier();
2037 if (namelen <= 0) {
2038 resvalue = -13;
2039 return 0;
2040 }
2041
2042 if (!inp->ShiftCurrent(namelen)) {
2043 resvalue = -13;
2044 return 0;
2045 }
2046 if (!inp->SkipSpaces()) {
2047 resvalue = -13;
2048 return 0;
2049 }
2050
2051 if (!inp->CheckFor("(")) {
2052 resvalue = -13;
2053 return 0;
2054 }
2055 if (inp->SearchFor(")") <= 0) {
2056 resvalue = -13;
2057 return 0;
2058 }
2059
2060 inp->SkipSpaces();
2061 if (*inp->fCurrent != '>') {
2062 resvalue = -13;
2063 return 0;
2064 }
2065 if (!inp->ShiftCurrent()) {
2066 resvalue = -13;
2067 return 0;
2068 }
2069 inp->SkipSpaces();
2070
2071 continue;
2072 }
2073
2074 break;
2075 }
2076
2077 if (!inp->CheckFor("]")) {
2078 resvalue = -13;
2079 return 0;
2080 }
2081 }
2082 inp->SkipSpaces();
2083 if (!inp->CheckFor(">")) {
2084 resvalue = -13;
2085 return 0;
2086 }
2087
2088 resvalue = 2;
2089 return node;
2090 }
2091
2092 EXmlNodeType nodetype = kXML_NODE;
2093 Bool_t canhaschildren = true;
2094 char endsymbol = '/';
2095
2096 // this is case of processing instructions node
2097 if (*inp->fCurrent == '?') {
2098 if (!inp->ShiftCurrent())
2099 return 0;
2100 nodetype = kXML_PI_NODE;
2101 canhaschildren = false;
2102 endsymbol = '?';
2103 }
2104
2105 if (!inp->SkipSpaces())
2106 return 0;
2107 Int_t len = inp->LocateIdentifier();
2108 if (len <= 0)
2109 return 0;
2110 node = (SXmlNode_t *)AllocateNode(len, xmlparent);
2111 char *nameptr = SXmlNode_t::Name(node);
2112 node->fType = nodetype;
2113
2114 strncpy(nameptr, inp->fCurrent, len); // here copied content without padding 0
2115 nameptr += len;
2116 *nameptr = 0; // add 0 to the end
2117
2118 char *colon = strchr(SXmlNode_t::Name(node), ':');
2119 if ((colon != 0) && (parent != 0)) {
2120 *colon = 0;
2121 node->fNs = (SXmlAttr_t *)FindNs(xmlparent, SXmlNode_t::Name(node));
2122 *colon = ':';
2123 }
2124
2125 if (!inp->ShiftCurrent(len))
2126 return 0;
2127
2128 do {
2129 if (!inp->SkipSpaces())
2130 return 0;
2131
2132 char nextsymb = *inp->fCurrent;
2133
2134 if (nextsymb == endsymbol) { // this is end of short node like <node ... />
2135 if (!inp->ShiftCurrent())
2136 return 0;
2137 if (*inp->fCurrent == '>') {
2138 if (!inp->ShiftCurrent())
2139 return 0;
2140
2141 if (node->fNs != 0)
2143
2144 inp->SkipSpaces(kTRUE); // locate start of next string
2145 resvalue = 2;
2146 return node;
2147 } else
2148 return 0;
2149 } else if (nextsymb == '>') { // this is end of parent node, lets find all children
2150 if (!canhaschildren) {
2151 resvalue = -11;
2152 return 0;
2153 }
2154
2155 if (!inp->ShiftCurrent())
2156 return 0;
2157
2158 do {
2159 ReadNode(node, inp, resvalue);
2160 } while (resvalue == 2);
2161
2162 if (resvalue == 1) {
2163 resvalue = 2;
2164 return node;
2165 } else
2166 return 0;
2167 } else {
2168 Int_t attrlen = inp->LocateIdentifier();
2169 if (attrlen <= 0) {
2170 resvalue = -6;
2171 return 0;
2172 }
2173
2174 int valuelen = inp->LocateValue(attrlen, true);
2175 if (valuelen < 3) {
2176 resvalue = -7;
2177 return 0;
2178 }
2179
2180 SXmlAttr_t *attr = (SXmlAttr_t *)AllocateAttr(attrlen, valuelen - 3, (XMLNodePointer_t)node);
2181
2182 char *attrname = SXmlAttr_t::Name(attr);
2183 strncpy(attrname, inp->fCurrent, attrlen);
2184 attrname += attrlen;
2185 *attrname = 0;
2186 attrname++;
2187 UnpackSpecialCharacters(attrname, inp->fCurrent + attrlen + 2, valuelen - 3);
2188
2189 if (!inp->ShiftCurrent(attrlen + valuelen))
2190 return 0;
2191
2192 attrname = SXmlAttr_t::Name(attr);
2193
2194 if ((strlen(attrname) > 6) && (strstr(attrname, "xmlns:") == attrname)) {
2195 if (strcmp(SXmlNode_t::Name(node), attrname + 6) != 0) {
2196 resvalue = -8;
2197 // return 0;
2198 }
2199 if (node->fNs != 0) {
2200 resvalue = -9;
2201 // return 0;
2202 }
2203 node->fNs = attr;
2204 }
2205 }
2206 } while (true);
2207
2208 return 0;
2209}
2210
2211////////////////////////////////////////////////////////////////////////////////
2212/// Displays xml parsing error
2213
2214void TXMLEngine::DisplayError(Int_t error, Int_t linenumber)
2215{
2216 switch (error) {
2217 case -14: Error("ParseFile", "Error include external XML file at line %d", linenumber); break;
2218 case -13: Error("ParseFile", "Error processing DTD part of XML file at line %d", linenumber); break;
2219 case -12: Error("ParseFile", "DOCTYPE missing after <! at line %d", linenumber); break;
2220 case -11:
2221 Error("ParseFile", "Node cannot be closed with > symbol at line %d, for instance <?xml ... ?> node", linenumber);
2222 break;
2223 case -10:
2224 Error("ParseFile", "Error in xml comments definition at line %d, must be <!-- comments -->", linenumber);
2225 break;
2226 case -9: Error("ParseFile", "Multiple namespace definitions not allowed, line %d", linenumber); break;
2227 case -8: Error("ParseFile", "Invalid namespace specification, line %d", linenumber); break;
2228 case -7: Error("ParseFile", "Invalid attribute value, line %d", linenumber); break;
2229 case -6: Error("ParseFile", "Invalid identifier for node attribute, line %d", linenumber); break;
2230 case -5: Error("ParseFile", "Mismatch between open and close nodes, line %d", linenumber); break;
2231 case -4: Error("ParseFile", "Unexpected close node, line %d", linenumber); break;
2232 case -3: Error("ParseFile", "Valid identifier for close node is missing, line %d", linenumber); break;
2233 case -2: Error("ParseFile", "No multiple content entries allowed, line %d", linenumber); break;
2234 case -1: Error("ParseFile", "Unexpected end of xml file"); break;
2235 default: Error("ParseFile", "XML syntax error at line %d", linenumber); break;
2236 }
2237}
PyObject * fType
#define d(i)
Definition: RSha256.hxx:102
int Int_t
Definition: RtypesCore.h:41
const Bool_t kFALSE
Definition: RtypesCore.h:88
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kTRUE
Definition: RtypesCore.h:87
#define ClassImp(name)
Definition: Rtypes.h:363
int type
Definition: TGX11.cxx:120
EXmlNodeType
Definition: TXMLEngine.cxx:40
@ kXML_COMMENT
Definition: TXMLEngine.cxx:42
@ kXML_PI_NODE
Definition: TXMLEngine.cxx:43
@ kXML_NODE
Definition: TXMLEngine.cxx:41
@ kXML_RAWLINE
Definition: TXMLEngine.cxx:44
@ kXML_CONTENT
Definition: TXMLEngine.cxx:45
void * XMLNodePointer_t
Definition: TXMLEngine.h:17
void * XMLNsPointer_t
Definition: TXMLEngine.h:18
void * XMLDocPointer_t
Definition: TXMLEngine.h:20
void * XMLAttrPointer_t
Definition: TXMLEngine.h:19
#define realloc
Definition: civetweb.c:1538
#define free
Definition: civetweb.c:1539
#define snprintf
Definition: civetweb.c:1540
#define malloc
Definition: civetweb.c:1536
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
An array of TObjects.
Definition: TObjArray.h:37
void Add(TObject *obj)
Definition: TObjArray.h:73
Int_t GetLast() const
Return index of last object in array.
Definition: TObjArray.cxx:561
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
Basic string class.
Definition: TString.h:131
TString & Append(const char *cs)
Definition: TString.h:559
Bool_t AddRawLine(XMLNodePointer_t parent, const char *line)
Add just line into xml file Line should has correct xml syntax that later it can be decoded by xml pa...
Definition: TXMLEngine.cxx:907
XMLNodePointer_t AllocateNode(int namelen, XMLNodePointer_t parent)
Allocates new xml node with specified name length.
const char * GetNSName(XMLNsPointer_t ns)
return name id of namespace
Definition: TXMLEngine.cxx:770
XMLNodePointer_t GetChild(XMLNodePointer_t xmlnode, Bool_t realnode=kTRUE)
returns first child of xmlnode
XMLAttrPointer_t NewAttr(XMLNodePointer_t xmlnode, XMLNsPointer_t, const char *name, const char *value)
creates new attribute for xmlnode, namespaces are not supported for attributes
Definition: TXMLEngine.cxx:578
XMLNsPointer_t NewNS(XMLNodePointer_t xmlnode, const char *reference, const char *name=0)
create namespace attribute for xmlnode.
Definition: TXMLEngine.cxx:733
void SaveSingleNode(XMLNodePointer_t xmlnode, TString *res, Int_t layout=1)
convert single xmlnode (and its child node) to string if layout<=0, no any spaces or newlines will be...
void SaveDoc(XMLDocPointer_t xmldoc, const char *filename, Int_t layout=1)
store document content to file if layout<=0, no any spaces or newlines will be placed between xmlnode...
void DisplayError(Int_t error, Int_t linenumber)
Displays xml parsing error.
Bool_t AddComment(XMLNodePointer_t parent, const char *comment)
Adds comment line to the node.
Definition: TXMLEngine.cxx:870
XMLNodePointer_t NewChild(XMLNodePointer_t parent, XMLNsPointer_t ns, const char *name, const char *content=0)
create new child element for parent node
Definition: TXMLEngine.cxx:707
void CleanNode(XMLNodePointer_t xmlnode)
remove all children node from xmlnode
void UnlinkNode(XMLNodePointer_t node)
unlink (detach) xmlnode from parent
Definition: TXMLEngine.cxx:997
void AssignDtd(XMLDocPointer_t xmldoc, const char *dtdname, const char *rootname)
assigns dtd filename to document
void FreeDoc(XMLDocPointer_t xmldoc)
frees allocated document data and deletes document itself
XMLNodePointer_t DocGetRootElement(XMLDocPointer_t xmldoc)
returns root node of document
void AddChild(XMLNodePointer_t parent, XMLNodePointer_t child)
add child element to xmlnode
Definition: TXMLEngine.cxx:791
XMLAttrPointer_t NewIntAttr(XMLNodePointer_t xmlnode, const char *name, Int_t value)
create node attribute with integer value
Definition: TXMLEngine.cxx:604
Bool_t AddDocComment(XMLDocPointer_t xmldoc, const char *comment)
add comment line to the top of the document
Definition: TXMLEngine.cxx:887
void AddNodeContent(XMLNodePointer_t xmlnode, const char *content, Int_t len=0)
add new content of the xmlnode old content will be preserved, one could mix content with child nodes
Bool_t HasAttr(XMLNodePointer_t xmlnode, const char *name)
checks if node has attribute of specified name
Definition: TXMLEngine.cxx:531
char * Makestr(const char *str)
creates char* variable with copy of provided string
Bool_t IsXmlNode(XMLNodePointer_t xmlnode)
return kTRUE is this is normal xmlnode
void SaveNode(XMLNodePointer_t xmlnode, TXMLOutputStream *out, Int_t layout, Int_t level)
stream data of xmlnode to output
Bool_t IsContentNode(XMLNodePointer_t xmlnode)
return kTRUE is this is special node with content
XMLAttrPointer_t GetNextAttr(XMLAttrPointer_t xmlattr)
return next attribute in the list
Definition: TXMLEngine.cxx:673
XMLDocPointer_t ParseStream(TXMLInputStream *input)
parses content of the stream and tries to produce xml structures
XMLNodePointer_t ReadSingleNode(const char *src)
read single xmlnode from provided string
const char * GetNSReference(XMLNsPointer_t ns)
return reference id of namespace
Definition: TXMLEngine.cxx:783
char * Makenstr(const char *start, int len)
creates char* variable with copy of len symbols from provided string
void SetNodeContent(XMLNodePointer_t xmlnode, const char *content, Int_t len=0)
set content of the xmlnode if old node content was exists, it will be replaced
const char * GetNodeContent(XMLNodePointer_t xmlnode)
get contents (if any) of xmlnode
XMLNsPointer_t GetNS(XMLNodePointer_t xmlnode)
return namespace attribute (if exists)
Definition: TXMLEngine.cxx:758
Bool_t IsEmptyNode(XMLNodePointer_t xmlnode)
return kTRUE is this is node with special data like comments to data processing instructions
Bool_t IsCommentNode(XMLNodePointer_t xmlnode)
return kTRUE is this is special node with content
const char * GetAttrName(XMLAttrPointer_t xmlattr)
return name of the attribute
Definition: TXMLEngine.cxx:684
XMLAttrPointer_t GetFirstAttr(XMLNodePointer_t xmlnode)
return first attribute in the list, namespace (if exists) will be skipped
Definition: TXMLEngine.cxx:657
const char * GetNodeName(XMLNodePointer_t xmlnode)
returns name of xmlnode
Bool_t AddDocRawLine(XMLDocPointer_t xmldoc, const char *line)
Add just line on the top of xml document Line should has correct xml syntax that later it can be deco...
Definition: TXMLEngine.cxx:924
XMLNodePointer_t ReadNode(XMLNodePointer_t xmlparent, TXMLInputStream *inp, Int_t &resvalue)
Tries to construct xml node from input stream.
void FreeAttr(XMLNodePointer_t xmlnode, const char *name)
remove attribute from xmlnode
Definition: TXMLEngine.cxx:614
Bool_t AddStyleSheet(XMLNodePointer_t parent, const char *href, const char *type="text/css", const char *title=0, int alternate=-1, const char *media=0, const char *charset=0)
Adds style sheet definition to the specified node Creates <?xml-stylesheet alternate="yes" title="com...
Definition: TXMLEngine.cxx:945
void OutputValue(char *value, TXMLOutputStream *out)
output value to output stream if symbols '<' '&' '>' '"' ''' appears in the string,...
const char * GetAttr(XMLNodePointer_t xmlnode, const char *name)
returns value of attribute for xmlnode
Definition: TXMLEngine.cxx:547
Bool_t ValidateVersion(XMLDocPointer_t doc, const char *version=0)
check that first node is xml processing instruction with correct xml version number
void AddChildAfter(XMLNodePointer_t parent, XMLNodePointer_t child, XMLNodePointer_t afternode)
Insert new child node after already existing node.
Definition: TXMLEngine.cxx:838
Bool_t fSkipComments
Definition: TXMLEngine.h:42
Int_t GetIntAttr(XMLNodePointer_t node, const char *name)
returns value of attribute as integer
Definition: TXMLEngine.cxx:563
XMLDocPointer_t NewDoc(const char *version="1.0")
creates new xml document with provided version
XMLNsPointer_t FindNs(XMLNodePointer_t xmlnode, const char *nsname)
define if namespace of that name exists for xmlnode
void UnlinkFreeNode(XMLNodePointer_t xmlnode)
combined operation. Unlink node and free used memory
XMLDocPointer_t ParseFile(const char *filename, Int_t maxbuf=100000)
Parses content of file and tries to produce xml structures.
TXMLEngine()
if true, do not create comments nodes in document during parsing
Definition: TXMLEngine.cxx:516
XMLAttrPointer_t AllocateAttr(int namelen, int valuelen, XMLNodePointer_t xmlnode)
Allocate new attribute with specified name length and value length.
void TruncateNsExtension(XMLNodePointer_t xmlnode)
removes namespace extension of nodename
void UnpackSpecialCharacters(char *target, const char *source, int srclen)
unpack special symbols, used in xml syntax to code characters these symbols: '<' - &lt,...
void FreeAllAttr(XMLNodePointer_t xmlnode)
Free all attributes of the node.
Definition: TXMLEngine.cxx:639
virtual ~TXMLEngine()
destructor for TXMLEngine object
Definition: TXMLEngine.cxx:524
XMLDocPointer_t ParseString(const char *xmlstring)
parses content of string and tries to produce xml structures
void FreeNode(XMLNodePointer_t xmlnode)
release all memory, allocated from this node and destroys node itself
Bool_t AddDocStyleSheet(XMLDocPointer_t xmldoc, const char *href, const char *type="text/css", const char *title=0, int alternate=-1, const char *media=0, const char *charset=0)
Add style sheet definition on the top of document.
Definition: TXMLEngine.cxx:978
const char * GetAttrValue(XMLAttrPointer_t xmlattr)
return value of attribute
Definition: TXMLEngine.cxx:695
XMLNodePointer_t GetNext(XMLNodePointer_t xmlnode, Bool_t realnode=kTRUE)
return next to xmlnode node if realnode==kTRUE, any special nodes in between will be skipped
void SkipEmpty(XMLNodePointer_t &xmlnode)
Skip all current empty nodes and locate on first "true" node.
void ShiftToNext(XMLNodePointer_t &xmlnode, Bool_t realnode=kTRUE)
shifts specified node to next if realnode==kTRUE, any special nodes in between will be skipped
void DocSetRootElement(XMLDocPointer_t xmldoc, XMLNodePointer_t xmlnode)
set main (root) node for document
XMLNodePointer_t GetParent(XMLNodePointer_t xmlnode)
returns parent of xmlnode
void AddChildFirst(XMLNodePointer_t parent, XMLNodePointer_t child)
add node as first child
Definition: TXMLEngine.cxx:816
TLine * line
const Int_t n
Definition: legend1.C:16
void Init(TClassEdit::TInterpreterLookupHelper *helper)
Definition: TClassEdit.cxx:121
static constexpr double ns
Definition: first.py:1
const char * Name
Definition: TXMLSetup.cxx:66
const char * cnt
Definition: TXMLSetup.cxx:74