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