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