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