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