XRootD
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"
38 #include "XrdXml/XrdXmlRdrXml2.hh"
39 
40 /******************************************************************************/
41 /* L o c a l D e f i n i t i o n s */
42 /******************************************************************************/
43 
44 namespace
45 {
46 // Develop a sane enum structure of xml node types
47 //
48 enum 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 
72 const 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 
103 XrdXmlRdrXml2::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 
142 void 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 
158 void XrdXmlRdrXml2::Free(void *strP) {xmlFree(strP);}
159 
160 /******************************************************************************/
161 /* G e t A t t r i b u t e s */
162 /******************************************************************************/
163 
164 bool 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 
210 int 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 
256 char *XrdXmlRdrXml2::GetName()
257 {
258  return (char *)xmlTextReaderName(reader);
259 }
260 
261 /******************************************************************************/
262 /* G e t T e x t */
263 /******************************************************************************/
264 
265 char *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 
297 bool XrdXmlRdrXml2::Init() {xmlInitParser(); return true;}
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)