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