1 #include <objson/xml2json.h>
3 struct osrfXMLGatewayParserStruct {
11 typedef struct osrfXMLGatewayParserStruct osrfXMLGatewayParser;
13 /** returns the attribute value with the given attribute name */
14 static char* getXMLAttr(const xmlChar** atts, char* attr_name) {
17 for(i = 0; (atts[i] != NULL); i++) {
18 if(strcmp((char*) atts[i++], attr_name) == 0) {
20 return (char*) atts[i];
28 static void appendChild(osrfXMLGatewayParser* p, jsonObject* obj) {
33 if(p->objStack->size == 0)
36 jsonObject* parent = OSRF_LIST_GET_INDEX(p->objStack, p->objStack->size - 1);
38 if(parent->type == JSON_ARRAY) {
39 jsonObjectPush(parent, obj);
41 char* key = osrfListPop(p->keyStack);
42 jsonObjectSetKey(parent, key, obj);
43 free(key); /* the list is not setup for auto-freeing */
49 static void startElementHandler(
50 void *parser, const xmlChar *name, const xmlChar **atts) {
52 osrfXMLGatewayParser* p = (osrfXMLGatewayParser*) parser;
55 char* hint = getXMLAttr(atts, "class_hint");
57 if(!strcmp((char*) name, "null")) {
58 appendChild(p, jsonNewObject(NULL));
62 if(!strcmp((char*) name, "string")) {
67 if(!strcmp((char*) name, "element")) {
68 osrfListPush(p->keyStack, strdup(getXMLAttr(atts, "key")));
72 if(!strcmp((char*) name, "object")) {
73 obj = jsonNewObject(NULL);
74 jsonObjectSetClass(obj, hint); /* OK if hint is NULL */
75 obj->type = JSON_HASH;
77 osrfListPush(p->objStack, obj);
81 if(!strcmp((char*) name, "array")) {
82 obj = jsonNewObject(NULL);
83 jsonObjectSetClass(obj, hint); /* OK if hint is NULL */
84 obj->type = JSON_ARRAY;
86 osrfListPush(p->objStack, obj);
91 if(!strcmp((char*) name, "number")) {
96 if(!strcmp((char*) name, "boolean")) {
97 obj = jsonNewObject(NULL);
98 obj->type = JSON_BOOL;
99 char* val = getXMLAttr(atts, "value");
100 if(val && !strcmp(val, "true"))
107 static void endElementHandler( void *parser, const xmlChar *name) {
108 if(!strcmp((char*) name, "array") || !strcmp((char*) name, "object")) {
109 osrfXMLGatewayParser* p = (osrfXMLGatewayParser*) parser;
110 osrfListPop(p->objStack);
114 static void characterHandler(void *parser, const xmlChar *ch, int len) {
117 strncpy(data, (char*) ch, len);
119 osrfXMLGatewayParser* p = (osrfXMLGatewayParser*) parser;
122 appendChild(p, jsonNewObject(data));
128 appendChild(p, jsonNewNumberObject(atof(data)));
134 static void parseWarningHandler(void *parser, const char* msg, ...) {
135 VA_LIST_TO_STRING(msg);
136 fprintf(stderr, "Parser warning %s\n", VA_BUF);
140 static void parseErrorHandler(void *parser, const char* msg, ...) {
142 VA_LIST_TO_STRING(msg);
143 fprintf(stderr, "Parser error %s\n", VA_BUF);
146 osrfXMLGatewayParser* p = (osrfXMLGatewayParser*) parser;
148 /* keyStack as strdup'ed strings. The list may
149 * not be empty, so tell it to free the items
150 * when it's freed (from the main routine)
152 osrfListSetDefaultFree(p->keyStack);
153 jsonObjectFree(p->obj);
162 static xmlSAXHandler SAXHandlerStruct = {
163 NULL, /* internalSubset */
164 NULL, /* isStandalone */
165 NULL, /* hasInternalSubset */
166 NULL, /* hasExternalSubset */
167 NULL, /* resolveEntity */
168 NULL, /* getEntity */
169 NULL, /* entityDecl */
170 NULL, /* notationDecl */
171 NULL, /* attributeDecl */
172 NULL, /* elementDecl */
173 NULL, /* unparsedEntityDecl */
174 NULL, /* setDocumentLocator */
175 NULL, /* startDocument */
176 NULL, /* endDocument */
177 startElementHandler, /* startElement */
178 endElementHandler, /* endElement */
179 NULL, /* reference */
180 characterHandler, /* characters */
181 NULL, /* ignorableWhitespace */
182 NULL, /* processingInstruction */
184 parseWarningHandler, /* xmlParserWarning */
185 parseErrorHandler, /* xmlParserError */
186 NULL, /* xmlParserFatalError : unused */
187 NULL, /* getParameterEntity */
188 NULL, /* cdataBlock; */
189 NULL, /* externalSubset; */
192 NULL, /* startElementNs */
193 NULL, /* endElementNs */
194 NULL /* xmlStructuredErrorFunc */
197 static const xmlSAXHandlerPtr SAXHandler = &SAXHandlerStruct;
199 jsonObject* jsonXMLToJSONObject(const char* xml) {
201 osrfXMLGatewayParser parser;
203 /* don't define freeItem, since objects will be cleaned by freeing the parent */
204 parser.objStack = osrfNewList();
205 /* don't define freeItem, since the list eill end up empty if there are no errors*/
206 parser.keyStack = osrfNewList();
211 xmlParserCtxtPtr ctxt = xmlCreatePushParserCtxt(SAXHandler, &parser, "", 0, NULL);
212 xmlParseChunk(ctxt, xml, strlen(xml), 1);
214 osrfListFree(parser.objStack);
215 osrfListFree(parser.keyStack);
216 xmlFreeParserCtxt(ctxt);
217 xmlCleanupCharEncodingHandlers();