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