Patch from Scott McKellar (including commentary):
[OpenSRF.git] / src / libopensrf / xml_utils.c
1 #include <opensrf/xml_utils.h>
2
3 /* helper function */
4 static jsonObject* _xmlToJSON(xmlNodePtr node, jsonObject*);
5
6 void recurse_doc( xmlNodePtr node ) {
7         if( node == NULL ) return;
8         printf("Recurse: %s =>  %s", node->name, node->content );
9         xmlNodePtr t = node->children;
10         while(t) {
11                 recurse_doc(t);
12                 t = t->next;
13         }
14 }
15
16
17
18 jsonObject* xmlDocToJSON(xmlDocPtr doc) {
19         if(!doc) return NULL;
20         return _xmlToJSON(xmlDocGetRootElement(doc), NULL);
21 }
22
23 static jsonObject* _xmlToJSON(xmlNodePtr node, jsonObject* obj) {
24
25         if(!node) return NULL;
26         if(xmlIsBlankNode(node)) return NULL;
27         if(obj == NULL) obj = jsonNewObject(NULL);
28
29         if(node->type == XML_TEXT_NODE) {
30                 jsonObjectSetString(obj, (char*) node->content);        
31
32         } else if(node->type == XML_ELEMENT_NODE || node->type == XML_ATTRIBUTE_NODE ) {
33
34                 jsonObject* new_obj = jsonNewObject(NULL);
35
36                 jsonObject* old;
37
38                 /* do the duplicate node / array shuffle */
39                 if( (old = jsonObjectGetKey(obj, (char*) node->name)) ) {
40                         if(old->type == JSON_ARRAY ) {
41                                 jsonObjectPush(old, new_obj);
42                         } else {
43                                 jsonObject* arr = jsonNewObject(NULL);
44                                 jsonObjectPush(arr, jsonObjectClone(old));
45                                 jsonObjectPush(arr, new_obj);
46                                 jsonObjectSetKey(obj, (char*) node->name, arr);
47                         }
48                 } else {
49                         jsonObjectSetKey(obj, (char*) node->name, new_obj);
50                 }
51
52                 xmlNodePtr child = node->children;
53                 if (child) { // at least one...
54                         if (child != node->last) { // more than one -- ignore TEXT nodes
55                                 while(child) {
56                                         if (child->type != XML_TEXT_NODE) _xmlToJSON(child, new_obj);
57                                         child = child->next;
58                                 }
59                         } else {
60                                 _xmlToJSON(child, new_obj);
61                         }
62                 }
63         }       
64
65         return obj;
66 }
67
68
69 char* xmlDocToString(xmlDocPtr doc, int full) {
70
71         if(!doc) return NULL;
72
73         char* xml;
74
75         if(full) {
76
77                 xmlChar* xmlbuf;
78                 int size;
79                 xmlDocDumpMemory(doc, &xmlbuf, &size);
80                 xml = strdup((char*) (xmlbuf));
81                 xmlFree(xmlbuf);
82                 return xml;
83
84         } else {
85
86                 xmlBufferPtr xmlbuf = xmlBufferCreate();
87                 xmlNodeDump( xmlbuf, doc, xmlDocGetRootElement(doc), 0, 0);
88                 xml = strdup((char*) (xmlBufferContent(xmlbuf)));
89                 xmlBufferFree(xmlbuf);
90                 return xml;
91
92         }
93 }
94
95
96
97
98 char* xmlSaxAttr( const xmlChar** atts, const char* name ) {
99         if( atts && name ) {
100                 int i;
101                 for(i = 0; (atts[i] != NULL); i++) {
102                         if(!strcmp((char*) atts[i], name)) {
103                                 if(atts[++i]) return (char*) atts[i];
104                         }
105                 }
106         }
107         return NULL;
108 }
109
110
111 int xmlAddAttrs( xmlNodePtr node, const xmlChar** atts ) {
112         if( node && atts ) {
113                 int i;
114                 for(i = 0; (atts[i] != NULL); i++) {
115                         if(atts[i+1]) {
116                                 xmlSetProp(node, atts[i], atts[i+1]);
117                                 i++;
118                         }
119                 }
120         }
121         return 0;
122 }
123