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