| 1 | #if 0
 | 
|---|
| 2 |     liblilxml
 | 
|---|
| 3 |     Copyright (C) 2003 Elwood C. Downey
 | 
|---|
| 4 | 
 | 
|---|
| 5 |     This library is free software; you can redistribute it and/or
 | 
|---|
| 6 |     modify it under the terms of the GNU Lesser General Public
 | 
|---|
| 7 |     License as published by the Free Software Foundation; either
 | 
|---|
| 8 |     version 2.1 of the License, or (at your option) any later version.
 | 
|---|
| 9 | 
 | 
|---|
| 10 |     This library is distributed in the hope that it will be useful,
 | 
|---|
| 11 |     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
| 12 |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
|---|
| 13 |     Lesser General Public License for more details.
 | 
|---|
| 14 | 
 | 
|---|
| 15 |     You should have received a copy of the GNU Lesser General Public
 | 
|---|
| 16 |     License along with this library; if not, write to the Free Software
 | 
|---|
| 17 |     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 | 
|---|
| 18 | 
 | 
|---|
| 19 | #endif
 | 
|---|
| 20 | 
 | 
|---|
| 21 | /** \file lilxml.h
 | 
|---|
| 22 |     \brief A little DOM-style library to handle parsing and processing an XML file.
 | 
|---|
| 23 |     
 | 
|---|
| 24 |     It only handles elements, attributes and pcdata content. <! ... > and <? ... > are silently ignored. pcdata is collected into one string, sans leading whitespace first line. \n
 | 
|---|
| 25 |     
 | 
|---|
| 26 |     The following is an example of a cannonical usage for the lilxml library. Initialize a lil xml context and read an XML file in a root element.
 | 
|---|
| 27 |     
 | 
|---|
| 28 |     \code
 | 
|---|
| 29 |     
 | 
|---|
| 30 |     #include <lilxml.h>
 | 
|---|
| 31 |     
 | 
|---|
| 32 |     LilXML *lp = newLilXML();
 | 
|---|
| 33 |         char errmsg[1024];
 | 
|---|
| 34 |         XMLEle *root, *ep;
 | 
|---|
| 35 |         int c;
 | 
|---|
| 36 | 
 | 
|---|
| 37 |         while ((c = fgetc(stdin)) != EOF) {
 | 
|---|
| 38 |             root = readXMLEle (lp, c, errmsg);
 | 
|---|
| 39 |             if (root)
 | 
|---|
| 40 |                 break;
 | 
|---|
| 41 |             if (errmsg[0])
 | 
|---|
| 42 |                 error ("Error: %s\n", errmsg);
 | 
|---|
| 43 |         }
 | 
|---|
| 44 |  
 | 
|---|
| 45 |         // print the tag and pcdata content of each child element within the root 
 | 
|---|
| 46 | 
 | 
|---|
| 47 |         for (ep = nextXMLEle (root, 1); ep != NULL; ep = nextXMLEle (root, 0))
 | 
|---|
| 48 |             printf ("%s: %s\n", tagXMLEle(ep), pcdataXMLEle(ep));
 | 
|---|
| 49 | 
 | 
|---|
| 50 | 
 | 
|---|
| 51 |         // finished with root element and with lil xml context
 | 
|---|
| 52 | 
 | 
|---|
| 53 |         delXMLEle (root);
 | 
|---|
| 54 |         delLilXML (lp);
 | 
|---|
| 55 |         
 | 
|---|
| 56 |      \endcode
 | 
|---|
| 57 |     
 | 
|---|
| 58 |  */
 | 
|---|
| 59 | 
 | 
|---|
| 60 | #ifndef LILXML_H
 | 
|---|
| 61 | #define LILXML_H
 | 
|---|
| 62 | 
 | 
|---|
| 63 | #include <stdio.h>
 | 
|---|
| 64 | 
 | 
|---|
| 65 | #ifdef __cplusplus
 | 
|---|
| 66 | extern "C" {
 | 
|---|
| 67 | #endif
 | 
|---|
| 68 | 
 | 
|---|
| 69 | /* opaque handle types */
 | 
|---|
| 70 | typedef struct _xml_att XMLAtt;
 | 
|---|
| 71 | typedef struct _xml_ele XMLEle;
 | 
|---|
| 72 | typedef struct _LilXML LilXML;
 | 
|---|
| 73 | 
 | 
|---|
| 74 | /**
 | 
|---|
| 75 |  * \defgroup lilxmlFunctions XML Functions: Functions to parse, process, and search XML.
 | 
|---|
| 76 |  */
 | 
|---|
| 77 | /*@{*/
 | 
|---|
| 78 | 
 | 
|---|
| 79 | /* creation and destruction functions */
 | 
|---|
| 80 | 
 | 
|---|
| 81 | /** \brief Create a new lilxml parser.
 | 
|---|
| 82 |     \return a pointer to the lilxml parser on success. NULL on failure.
 | 
|---|
| 83 | */
 | 
|---|
| 84 | extern LilXML *newLilXML(void);
 | 
|---|
| 85 | 
 | 
|---|
| 86 | /** \brief Delete a lilxml parser.
 | 
|---|
| 87 |     \param lp a pointer to a lilxml parser to be deleted.
 | 
|---|
| 88 | */
 | 
|---|
| 89 | extern void delLilXML (LilXML *lp);
 | 
|---|
| 90 | 
 | 
|---|
| 91 | /** \brief Delete an XML element.
 | 
|---|
| 92 |     \return a pointer to the XML Element to be deleted.
 | 
|---|
| 93 | */
 | 
|---|
| 94 | extern void delXMLEle (XMLEle *e);
 | 
|---|
| 95 | 
 | 
|---|
| 96 | /** \brief Process an XML one char at a time.
 | 
|---|
| 97 |     \param lp a pointer to a lilxml parser.
 | 
|---|
| 98 |     \param c one character to process.
 | 
|---|
| 99 |     \param errmsg a buffer to store error messages if an error in parsing is encounterd.
 | 
|---|
| 100 |     \return When the function parses a complete valid XML element, it will return a pointer to the XML element. A NULL is returned when parsing the element is still in progress, or if a parsing error occurs. Check errmsg for errors if NULL is returned. 
 | 
|---|
| 101 |  */
 | 
|---|
| 102 | extern XMLEle *readXMLEle (LilXML *lp, int c, char errmsg[]);
 | 
|---|
| 103 | 
 | 
|---|
| 104 | /* search functions */
 | 
|---|
| 105 | /** \brief Find an XML attribute within an XML element.
 | 
|---|
| 106 |     \param e a pointer to the XML element to search.
 | 
|---|
| 107 |     \param name the attribute name to search for.
 | 
|---|
| 108 |     \return A pointer to the XML attribute if found or NULL on failure.
 | 
|---|
| 109 | */
 | 
|---|
| 110 | extern XMLAtt *findXMLAtt (XMLEle *e, const char *name);
 | 
|---|
| 111 | 
 | 
|---|
| 112 | /** \brief Find an XML element within an XML element.
 | 
|---|
| 113 |     \param e a pointer to the XML element to search.
 | 
|---|
| 114 |     \param tag the element tag to search for.
 | 
|---|
| 115 |     \return A pointer to the XML element if found or NULL on failure.
 | 
|---|
| 116 | */
 | 
|---|
| 117 | extern XMLEle *findXMLEle (XMLEle *e, const char *tag);
 | 
|---|
| 118 | 
 | 
|---|
| 119 | /* iteration functions */
 | 
|---|
| 120 | /** \brief Iterate an XML element for a list of nesetd XML elements.
 | 
|---|
| 121 |     \param ep a pointer to the XML element to iterate.
 | 
|---|
| 122 |     \param first the index of the starting XML element. Pass 1 to start iteration from the beginning of the XML element. Pass 0 to get the next element thereater. 
 | 
|---|
| 123 |     \return On success, a pointer to the next XML element is returned. NULL when there are no more elements.
 | 
|---|
| 124 | */
 | 
|---|
| 125 | extern XMLEle *nextXMLEle (XMLEle *ep, int first);
 | 
|---|
| 126 | 
 | 
|---|
| 127 | /** \brief Iterate an XML element for a list of XML attributes.
 | 
|---|
| 128 |     \param ep a pointer to the XML element to iterate.
 | 
|---|
| 129 |     \param first the index of the starting XML attribute. Pass 1 to start iteration from the beginning of the XML element. Pass 0 to get the next attribute thereater. 
 | 
|---|
| 130 |     \return On success, a pointer to the next XML attribute is returned. NULL when there are no more attributes.
 | 
|---|
| 131 | */
 | 
|---|
| 132 | extern XMLAtt *nextXMLAtt (XMLEle *ep, int first);
 | 
|---|
| 133 | 
 | 
|---|
| 134 | /* tree functions */
 | 
|---|
| 135 | /** \brief Return the parent of an XML element.
 | 
|---|
| 136 |     \return a pointer to the XML element parent.
 | 
|---|
| 137 | */
 | 
|---|
| 138 | extern XMLEle *parentXMLEle (XMLEle *ep);
 | 
|---|
| 139 | 
 | 
|---|
| 140 | /** \brief Return the parent of an XML attribute.
 | 
|---|
| 141 |     \return a pointer to the XML element parent.
 | 
|---|
| 142 | */
 | 
|---|
| 143 | extern XMLEle *parentXMLAtt (XMLAtt *ap);
 | 
|---|
| 144 | 
 | 
|---|
| 145 | /* access functions */
 | 
|---|
| 146 | /** \brief Return the tag of an XML element.
 | 
|---|
| 147 |     \param ep a pointer to an XML element.
 | 
|---|
| 148 |     \return the tag string.
 | 
|---|
| 149 | */
 | 
|---|
| 150 | extern char *tagXMLEle (XMLEle *ep);
 | 
|---|
| 151 | 
 | 
|---|
| 152 | /** \brief Return the pcdata of an XML element.
 | 
|---|
| 153 |     \param ep a pointer to an XML element.
 | 
|---|
| 154 |     \return the pcdata string on success.
 | 
|---|
| 155 | */
 | 
|---|
| 156 | extern char *pcdataXMLEle (XMLEle *ep);
 | 
|---|
| 157 | 
 | 
|---|
| 158 | /** \brief Return the name of an XML attribute.
 | 
|---|
| 159 |     \param ap a pointer to an XML attribute.
 | 
|---|
| 160 |     \return the name string of the attribute.
 | 
|---|
| 161 | */
 | 
|---|
| 162 | extern char *nameXMLAtt (XMLAtt *ap);
 | 
|---|
| 163 | 
 | 
|---|
| 164 | /** \brief Return the value of an XML attribute.
 | 
|---|
| 165 |     \param ap a pointer to an XML attribute.
 | 
|---|
| 166 |     \return the value string of the attribute.
 | 
|---|
| 167 | */
 | 
|---|
| 168 | extern char *valuXMLAtt (XMLAtt *ap);
 | 
|---|
| 169 | 
 | 
|---|
| 170 | /** \brief Return the number of characters in pcdata in an XML element.
 | 
|---|
| 171 |     \param ep a pointer to an XML element.
 | 
|---|
| 172 |     \return the length of the pcdata string.
 | 
|---|
| 173 | */
 | 
|---|
| 174 | extern int pcdatalenXMLEle (XMLEle *ep);
 | 
|---|
| 175 | 
 | 
|---|
| 176 | /** \brief Return the number of nested XML elements in a parent XML element.
 | 
|---|
| 177 |     \param ep a pointer to an XML element.
 | 
|---|
| 178 |     \return the number of nested XML elements.
 | 
|---|
| 179 | */
 | 
|---|
| 180 | extern int nXMLEle (XMLEle *ep);
 | 
|---|
| 181 | 
 | 
|---|
| 182 | /** \brief Return the number of XML attributes in a parent XML element.
 | 
|---|
| 183 |     \param ep a pointer to an XML element.
 | 
|---|
| 184 |     \return the number of XML attributes within the XML element.
 | 
|---|
| 185 | */
 | 
|---|
| 186 | extern int nXMLAtt (XMLEle *ep);
 | 
|---|
| 187 | 
 | 
|---|
| 188 | /* editing functions */
 | 
|---|
| 189 | /** \brief add an element with the given tag to the given element. parent can be NULL to make a new root.
 | 
|---|
| 190 |     \return if parent is NULL, a new root is returned, otherwise, parent is returned.
 | 
|---|
| 191 | */
 | 
|---|
| 192 | extern XMLEle *addXMLEle (XMLEle *parent, const char *tag);
 | 
|---|
| 193 | 
 | 
|---|
| 194 | /** \brief set the pcdata of the given element
 | 
|---|
| 195 |     \param ep pointer to an XML element.
 | 
|---|
| 196 |     \param pcdata pcdata to set.
 | 
|---|
| 197 | */
 | 
|---|
| 198 | extern void editXMLEle (XMLEle *ep, const char *pcdata);
 | 
|---|
| 199 | 
 | 
|---|
| 200 | /** \brief Add an XML attribute to an existing XML element.
 | 
|---|
| 201 |     \param ep pointer to an XML element
 | 
|---|
| 202 |     \param name the name of the XML attribute to add.
 | 
|---|
| 203 |     \param value the value of the XML attribute to add.
 | 
|---|
| 204 | */
 | 
|---|
| 205 | extern XMLAtt* addXMLAtt (XMLEle *ep, const char *name, const char *value);
 | 
|---|
| 206 | 
 | 
|---|
| 207 | /** \brief Remove an XML attribute from an XML element.
 | 
|---|
| 208 |     \param ep pointer to an XML element.
 | 
|---|
| 209 |     \param name the name of the XML attribute to remove
 | 
|---|
| 210 | */
 | 
|---|
| 211 | extern void rmXMLAtt (XMLEle *ep, const char *name);
 | 
|---|
| 212 | 
 | 
|---|
| 213 | /** \brief change the value of an attribute to str.
 | 
|---|
| 214 | *   \param ap pointer to XML attribute
 | 
|---|
| 215 | *   \param str new attribute value
 | 
|---|
| 216 | */
 | 
|---|
| 217 | extern void editXMLAtt (XMLAtt *ap, const char *str);
 | 
|---|
| 218 | 
 | 
|---|
| 219 | /** \brief return a string with all xml-sensitive characters within the passed string replaced with their entity sequence equivalents.
 | 
|---|
| 220 | *   N.B. caller must use the returned string before calling us again.
 | 
|---|
| 221 | */
 | 
|---|
| 222 | extern char *entityXML (char *str);
 | 
|---|
| 223 | 
 | 
|---|
| 224 | /* convenience functions */
 | 
|---|
| 225 | /** \brief Find an XML element's attribute value.
 | 
|---|
| 226 |     \param ep a pointer to an XML element.
 | 
|---|
| 227 |     \param name the name of the XML attribute to retrieve its value.
 | 
|---|
| 228 |     \return the value string of an XML element on success. NULL on failure.
 | 
|---|
| 229 | */
 | 
|---|
| 230 | extern const char *findXMLAttValu (XMLEle *ep, const char *name);
 | 
|---|
| 231 | 
 | 
|---|
| 232 | /** \brief Handy wrapper to read one xml file.
 | 
|---|
| 233 |     \param fp pointer to FILE to read.
 | 
|---|
| 234 |     \param lp pointer to lilxml parser.
 | 
|---|
| 235 |     \param errmsg a buffer to store error messages on failure.
 | 
|---|
| 236 |     \return root element else NULL with report in errmsg[].
 | 
|---|
| 237 | */
 | 
|---|
| 238 | extern XMLEle *readXMLFile (FILE *fp, LilXML *lp, char errmsg[]);
 | 
|---|
| 239 | 
 | 
|---|
| 240 | /** \brief Print an XML element.
 | 
|---|
| 241 |     \param fp a pointer to FILE where the print output is directed.
 | 
|---|
| 242 |     \param e the XML element to print.
 | 
|---|
| 243 |     \param level the printing level, set to 0 to print the whole element.
 | 
|---|
| 244 | */
 | 
|---|
| 245 | extern void prXMLEle (FILE *fp, XMLEle *e, int level);
 | 
|---|
| 246 | 
 | 
|---|
| 247 | /** \brief sample print ep to string s.
 | 
|---|
| 248 | *   N.B. s must be at least as large as that reported by sprlXMLEle()+1.
 | 
|---|
| 249 | *   N.B. set level = 0 on first call.
 | 
|---|
| 250 | *   \return return length of resulting string (sans trailing \0)
 | 
|---|
| 251 | */
 | 
|---|
| 252 | extern int sprXMLEle (char *s, XMLEle *ep, int level);
 | 
|---|
| 253 | 
 | 
|---|
| 254 | /** \brief return number of bytes in a string guaranteed able to hold result of sprXLMEle(ep) (sans trailing \0).
 | 
|---|
| 255 | *   N.B. set level = 0 on first call.
 | 
|---|
| 256 | */
 | 
|---|
| 257 | extern int sprlXMLEle (XMLEle *ep, int level);
 | 
|---|
| 258 | 
 | 
|---|
| 259 | /* install alternatives to malloc/realloc/free */
 | 
|---|
| 260 | extern void indi_xmlMalloc (void *(*newmalloc)(size_t size),
 | 
|---|
| 261 |     void *(*newrealloc)(void *ptr, size_t size), void (*newfree)(void *ptr));
 | 
|---|
| 262 | 
 | 
|---|
| 263 | /*@}*/
 | 
|---|
| 264 | 
 | 
|---|
| 265 | #ifdef __cplusplus
 | 
|---|
| 266 | }
 | 
|---|
| 267 | #endif
 | 
|---|
| 268 | 
 | 
|---|
| 269 | /* examples.
 | 
|---|
| 270 | 
 | 
|---|
| 271 |         initialize a lil xml context and read an XML file in a root element
 | 
|---|
| 272 | 
 | 
|---|
| 273 |         LilXML *lp = newLilXML();
 | 
|---|
| 274 |         char errmsg[1024];
 | 
|---|
| 275 |         XMLEle *root, *ep;
 | 
|---|
| 276 |         int c;
 | 
|---|
| 277 | 
 | 
|---|
| 278 |         while ((c = fgetc(stdin)) != EOF) {
 | 
|---|
| 279 |             root = readXMLEle (lp, c, errmsg);
 | 
|---|
| 280 |             if (root)
 | 
|---|
| 281 |                 break;
 | 
|---|
| 282 |             if (errmsg[0])
 | 
|---|
| 283 |                 error ("Error: %s\n", errmsg);
 | 
|---|
| 284 |         }
 | 
|---|
| 285 |  
 | 
|---|
| 286 |         print the tag and pcdata content of each child element within the root
 | 
|---|
| 287 | 
 | 
|---|
| 288 |         for (ep = nextXMLEle (root, 1); ep != NULL; ep = nextXMLEle (root, 0))
 | 
|---|
| 289 |             printf ("%s: %s\n", tagXMLEle(ep), pcdataXMLEle(ep));
 | 
|---|
| 290 | 
 | 
|---|
| 291 | 
 | 
|---|
| 292 |         finished with root element and with lil xml context
 | 
|---|
| 293 | 
 | 
|---|
| 294 |         delXMLEle (root);
 | 
|---|
| 295 |         delLilXML (lp);
 | 
|---|
| 296 |  */
 | 
|---|
| 297 | 
 | 
|---|
| 298 | /* For RCS Only -- Do Not Edit
 | 
|---|
| 299 |  * @(#) $RCSfile$ $Date: 2007-09-17 16:34:48 +0300 (Mon, 17 Sep 2007) $ $Revision: 713418 $ $Name:  $
 | 
|---|
| 300 |  */
 | 
|---|
| 301 | 
 | 
|---|
| 302 | #endif  /* LILXML_H */
 | 
|---|