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