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