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