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