XRootD
Loading...
Searching...
No Matches
XrdXmlRdrXml2.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d X m l R d r X m l 2 . c c */
4/* */
5/* (c) 2015 by the Board of Trustees of the Leland Stanford, Jr., University */
6/* Produced by Andrew Hanushevsky for Stanford University under contract */
7/* DE-AC02-76-SFO0515 with the Department of Energy */
8/* */
9/* This file is part of the XRootD software suite. */
10/* */
11/* XRootD is free software: you can redistribute it and/or modify it under */
12/* the terms of the GNU Lesser General Public License as published by the */
13/* Free Software Foundation, either version 3 of the License, or (at your */
14/* option) any later version. */
15/* */
16/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19/* License for more details. */
20/* */
21/* You should have received a copy of the GNU Lesser General Public License */
22/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24/* */
25/* The copyright holder's institutional names and contributor's names may not */
26/* be used to endorse or promote products derived from this software without */
27/* specific prior written permission of the institution or contributor. */
28/******************************************************************************/
29
30#include <cctype>
31#include <cstdlib>
32#include <cstring>
33#include <iostream>
34
35#include <libxml/xmlreader.h>
36
37#include "XrdSys/XrdSysE2T.hh"
39
40/******************************************************************************/
41/* L o c a l D e f i n i t i o n s */
42/******************************************************************************/
43
44namespace
45{
46// Develop a sane enum structure of xml node types
47//
48enum XmlNodeType {ntNone = XML_READER_TYPE_NONE,
49 ntElmBeg = XML_READER_TYPE_ELEMENT,
50 ntAttr = XML_READER_TYPE_ATTRIBUTE,
51 ntText = XML_READER_TYPE_TEXT,
52 ntCData = XML_READER_TYPE_CDATA,
53 ntEntRef = XML_READER_TYPE_ENTITY_REFERENCE,
54 ntEntBeg = XML_READER_TYPE_ENTITY,
55 ntPI = XML_READER_TYPE_PROCESSING_INSTRUCTION,
56 ntCmt = XML_READER_TYPE_COMMENT,
57 ntDoc = XML_READER_TYPE_DOCUMENT,
58 ntDTD = XML_READER_TYPE_DOCUMENT_TYPE,
59 ntDFrag = XML_READER_TYPE_DOCUMENT_FRAGMENT,
60 ntNote = XML_READER_TYPE_NOTATION,
61 ntWSpace = XML_READER_TYPE_WHITESPACE,
62 ntWSpSig = XML_READER_TYPE_SIGNIFICANT_WHITESPACE,
63 ntElmEnd = XML_READER_TYPE_END_ELEMENT,
64 ntEntEnd = XML_READER_TYPE_END_ENTITY,
65 ntXMLDcl = XML_READER_TYPE_XML_DECLARATION
66 };
67
68/******************************************************************************/
69/* X m l N o d e N a m e */
70/******************************************************************************/
71
72const char *NodeName(int ntype)
73{
74 switch(ntype)
75 {case ntNone: return "isNode "; break;
76 case ntElmBeg: return "isElmBeg"; break;
77 case ntAttr: return "isAttr "; break;
78 case ntText: return "isText "; break;
79 case ntCData: return "isCData "; break;
80 case ntEntRef: return "isEntRef"; break;
81 case ntEntBeg: return "isEntBeg"; break;
82 case ntPI: return "isPI "; break;
83 case ntCmt: return "isCmt "; break;
84 case ntDoc: return "isDoc "; break;
85 case ntDTD: return "isDTD "; break;
86 case ntDFrag: return "isDFrag "; break;
87 case ntWSpace: return "isWSpace"; break;
88 case ntWSpSig: return "isWSpSig"; break;
89 case ntNote: return "isNote "; break;
90 case ntElmEnd: return "isElmEnd"; break;
91 case ntEntEnd: return "isEntEnd"; break;
92 case ntXMLDcl: return "isXMLDcl"; break;
93 default: break;
94 };
95 return "???";
96}
97}
98
99/******************************************************************************/
100/* C o n s t r c u t o r # 1 */
101/******************************************************************************/
102
103XrdXmlRdrXml2::XrdXmlRdrXml2(bool &aOK, const char *fname, const char *enc)
104{
105// Initialize the standard values
106//
107 encType = (enc ? strdup(enc) : 0);
108 eCode = 0;
109 *eText = 0;
110 doDup = true; // We always duplicate memory to avoid allocator issues
111 debug = getenv("XrdXmlDEBUG") != 0;
112
113// Get a file reader
114//
115 if (!(reader = xmlNewTextReaderFilename(fname)))
116 {if ((eCode = errno))
117 {size_t size = sizeof(eText) - 1;
118 strncpy(eText, XrdSysE2T(errno), size);
119 eText[size] = '\0';
120 }
121 else strcpy(eText, "Unknown error opening input file");
122 aOK = false;
123 } else aOK = true;
124}
125
126/******************************************************************************/
127/* D e s t r u c t o r */
128/******************************************************************************/
129
131{
132
133// Tear down the reader
134//
135 xmlFreeTextReader(reader); reader = 0;
136}
137
138/******************************************************************************/
139/* Private: D e b u g */
140/******************************************************************************/
141
142void XrdXmlRdrXml2::Debug(const char *hdr, const char *want, char *have,
143 const char *scope, int nType)
144{
145 char buff[512];
146
147// Format the message
148//
149 snprintf(buff,sizeof(buff),"%s %s depth: %d scope: %s want: %s have: %s\n",
150 hdr,NodeName(nType),xmlTextReaderDepth(reader),scope,want,have);
151 std::cerr <<buff <<std::flush;
152}
153
154/******************************************************************************/
155/* F r e e */
156/******************************************************************************/
157
158void XrdXmlRdrXml2::Free(void *strP) {xmlFree(strP);}
159
160/******************************************************************************/
161/* G e t A t t r i b u t e s */
162/******************************************************************************/
163
164bool XrdXmlRdrXml2::GetAttributes(const char **aname, char **aval)
165{
166 char *name, *value;
167 int i;
168 bool found = false;
169
170// If we are not at the begining of an element, this is a sequence error
171//
172 if (xmlTextReaderNodeType(reader) != ntElmBeg)
173 {snprintf(eText, sizeof(eText),
174 "Illegal position seeking attribute %s",aname[0]);
175 eCode = EILSEQ;
176 return false;
177 }
178
179// Find the attribute
180//
181 while(xmlTextReaderMoveToNextAttribute(reader))
182 {if ((name = GetName()))
183 {i = 0;
184 while(aname[i] && strcmp(name, aname[i])) i++;
185 xmlFree(name);
186 if (aname[i])
187 {if (!(value = (char *)xmlTextReaderValue(reader))) continue;
188 found = true;
189 if (doDup)
190 {if (aval[i]) free(aval[i]);
191 aval[i] = strdup(value);
192 xmlFree(value);
193 } else {
194 if (aval[i]) xmlFree(aval[i]);
195 aval[i] = value;
196 }
197 }
198 }
199 }
200
201// All done
202//
203 return found;
204}
205
206/******************************************************************************/
207/* G e t E l e m e n t */
208/******************************************************************************/
209
210int XrdXmlRdrXml2::GetElement(const char **ename, bool reqd)
211{
212 char *name = 0;
213 int i, nType;
214
215// Scan over to the wanted element
216//
217 while(xmlTextReaderRead(reader) == 1)
218 {nType = xmlTextReaderNodeType(reader);
219 if (nType == ntWSpSig || !(name = GetName())) continue;
220
221 if (nType == ntElmEnd)
222 {if (debug) Debug("getelem:",ename[1],name,ename[0],nType);
223 if (!strcmp(name, ename[0])) break;
224 }
225 else if (nType == ntElmBeg)
226 {i = 1;
227 while(ename[i] && strcmp(name, ename[i])) i++;
228 if (ename[i])
229 {if (debug) Debug("getelem:",ename[i],name,ename[0],nType);
230 xmlFree(name);
231 return i;
232 }
233 if (debug) Debug("getelem:",ename[1],name,ename[0],nType);
234 xmlFree(name);
235 }
236 }
237
238// Free any allocate storage
239//
240 if (name) xmlFree(name);
241
242// This is an error if this element was required
243//
244 if (reqd)
245 {snprintf(eText,sizeof(eText),"Required element '%s' not found in %s",
246 (ename[1] ? ename[1] : "???"), ename[0]);
247 eCode = ESRCH;
248 }
249 return 0;
250}
251
252/******************************************************************************/
253/* Private: G e t N a m e */
254/******************************************************************************/
255
256char *XrdXmlRdrXml2::GetName()
257{
258 return (char *)xmlTextReaderName(reader);
259}
260
261/******************************************************************************/
262/* G e t T e x t */
263/******************************************************************************/
264
265char *XrdXmlRdrXml2::GetText(const char *ename, bool reqd)
266{
267 char *sP, *value = 0;
268
269// Get next element and make sure it exists and is text
270//
271 if (xmlTextReaderRead(reader) == 1
272 && xmlTextReaderNodeType(reader) == ntText)
273 {if ((value = (char *)xmlTextReaderValue(reader)) && !(*value))
274 {xmlFree(value); value = 0;}
275 }
276
277// We did not find a value. If not required return.
278//
279 if (value || !reqd)
280 {if (!doDup || !value) return value;
281 sP = strdup(value);
282 xmlFree(value);
283 return sP;
284 }
285
286// Create error message
287//
288 snprintf(eText,sizeof(eText),"Required %s tag text value not found",ename);
289 eCode = ENOMSG;
290 return 0;
291}
292
293/******************************************************************************/
294/* I n i t */
295/******************************************************************************/
296
297bool XrdXmlRdrXml2::Init() {xmlInitParser(); return true;}
bool Debug
const char * XrdSysE2T(int errcode)
Definition XrdSysE2T.cc:104
virtual char * GetText(const char *ename, bool reqd=false)
XrdXmlRdrXml2(bool &aOK, const char *fname, const char *enc=0)
Constructor & Destructor.
virtual int GetElement(const char **ename, bool reqd=false)
virtual void Free(void *strP)
static bool Init()
virtual ~XrdXmlRdrXml2()
virtual bool GetAttributes(const char **aname, char **aval)