work on figuring more stuff out--may want to revert this commit
[pspp] / parse-xml.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <libxml/parser.h>
4 #include <libxml/tree.h>
5
6 static void
7 print_parents(xmlNode *node)
8 {
9   for (; node; node = node->next)
10     {
11       if (node->type == XML_ELEMENT_NODE)
12         {
13           for (xmlNode *child = node->children; child; child = child->next)
14             {
15               if (child->type == XML_ELEMENT_NODE)
16                   printf ("%s %s\n", node->name, child->name);
17               else if (child->type == XML_TEXT_NODE)
18                 printf ("%s <text>\n", node->name);
19               else if (child->type == XML_CDATA_SECTION_NODE)
20                 printf ("%s <cdata>\n", node->name);
21               else if (child->type == XML_COMMENT_NODE)
22                 printf ("%s <comment>\n", node->name);
23               else
24                 printf ("%s <%d>\n", node->name, child->type);
25             }
26         }
27
28       print_parents (node->children);
29     }
30 }
31
32 static void
33 print_containment (xmlNode *node)
34 {
35   for (; node; node = node->next)
36     {
37       if (node->type == XML_ELEMENT_NODE)
38         {
39           const char *child_names[5000];
40           int child_name_cnt[5000];
41           int n_names = 0;
42           for (xmlNode *child = node->children; child; child = child->next)
43             {
44               const char *name;
45
46               if (child->type == XML_ELEMENT_NODE)
47                 {
48                   name = (char *) child->name;
49                   if (!strcmp((char *) node->name, "derivedVariable")
50                       && !strcmp((char *) name, "extension"))
51                     {
52                       char *p;
53                       asprintf(&p, "%s/%s", 
54                                (char *) xmlGetProp (child, (xmlChar *) "from"),
55                                (char *) xmlGetProp (child, (xmlChar *) "helpId"));
56                       name = p;
57                     }
58                 }
59               else if (child->type == XML_TEXT_NODE)
60                 name = "<text>";
61               else if (child->type == XML_CDATA_SECTION_NODE)
62                 name = "<cdata>";
63               else if (child->type == XML_COMMENT_NODE)
64                 {
65                   name = "<comment>";
66                   //printf ("comment %s\n", (char *) child->content);
67                   continue;
68                 }
69               else
70                 name = "<other>";
71
72 #if 0
73               for (int i = 0; i < n_names; i++)
74                 if (!strcmp(name, child_names[i]))
75                   {
76                     child_name_cnt[i]++;
77                     goto next;
78                   }
79 #endif
80               child_names[n_names] = name;
81               child_name_cnt[n_names] = 1;
82               n_names++;
83
84               //next:;
85             }
86
87           printf ("%s", node->name);
88           for (int i = 0; i < n_names; i++)
89             {
90               printf (" %s", child_names[i]);
91               if (child_name_cnt[i] > 1)
92                 printf ("+");
93             }
94           printf ("\n");
95         }
96
97       print_containment (node->children);
98     }
99 }
100
101 static void
102 print_labels (xmlNode *node)
103 {
104   for (; node; node = node->next)
105     {
106       if (node->type == XML_ELEMENT_NODE
107           && !strcmp((char *) node->name, "label")
108           && node->parent->type == XML_ELEMENT_NODE
109           && !strcmp((char *) node->parent->name, "container"))
110         {
111           for (xmlNode *child = node->children; child; child = child->next)
112             if (child->type == XML_TEXT_NODE)
113               puts ((char *) child->content);
114         }
115
116       print_labels (node->children);
117     }
118 }
119
120 static int
121 compare_strings(const void *a_, const void *b_)
122 {
123   const void *const *ap = a_;
124   const void *const *bp = b_;
125   return strcmp (*ap, *bp);
126 }
127
128 static void
129 print_attributes (xmlNode * a_node)
130 {
131   for (xmlNode *node = a_node; node; node = node->next)
132     {
133       if (node->type == XML_ELEMENT_NODE)
134         {
135           printf ("%s<-%s", node->name, node->parent->name);
136
137           char *attrs[500];
138           int n_attrs = 0;
139           for (xmlAttr *attr = node->properties; attr; attr = attr->next)
140             if (!strcmp((char *) attr->name, "baseFormat"))
141               printf(" baseFormat=%s", attr->children->content);
142             else
143               attrs[n_attrs++] = (char *) attr->name;
144           qsort(attrs, n_attrs, sizeof *attrs, compare_strings);
145
146           for (int i = 0; i < n_attrs; i++)
147             printf (" %s", attrs[i]);
148           putchar ('\n');
149         }
150
151       print_attributes (node->children);
152     }
153 }
154
155 static void
156 print_string(xmlChar *s)
157 {
158   for (char *p = (char *) s; *p; p++)
159     if (*p == '\n')
160       printf ("\\n");
161     else
162       putchar (*p);
163 }
164
165 static void
166 print_cdata (xmlNode * a_node)
167 {
168   for (xmlNode *node = a_node; node; node = node->next)
169     {
170       if (node->type == XML_CDATA_SECTION_NODE)
171         {
172           print_string (node->content);
173           putchar ('\n');
174         }
175
176       print_cdata (node->children);
177     }
178 }
179
180 static void
181 print_attribute (xmlNode *node, const char *attr)
182 {
183   for (; node; node = node->next)
184     {
185       const char *s = (char *) xmlGetProp (node, (xmlChar *) attr);
186       if (s)
187         printf ("%s %s=%s\n", node->name, attr, s);
188
189       print_attribute (node->children, attr);
190     }
191 }
192
193 static void
194 print_element (xmlDoc *doc, xmlNode *node, const char *element)
195 {
196   for (; node; node = node->next)
197     {
198       if (!strcmp(element, (char *) node->name))
199         {
200           xmlBuffer *buf = xmlBufferCreate();
201           xmlNodeDump (buf, doc, node, 0, 1);
202           xmlBufferDump (stdout, buf);
203           xmlBufferFree (buf);
204           putchar ('\n');
205         }
206
207       print_element (doc, node->children, element);
208     }
209 }
210
211 static __attribute__((unused)) xmlNode *
212 find_page_setup (xmlNode *node)
213 {
214   for (; node; node = node->next)
215     {
216       if (node->name && !strcmp ((char *) node->name, "pageSetup"))
217         return node;
218
219       xmlNode *ps = find_page_setup (node->children);
220       if (ps)
221         return ps;
222     }
223   return NULL;
224 }
225
226 static void
227 print_text (xmlNode *node)
228 {
229   for (; node; node = node->next)
230     {
231       if (node->type == XML_ELEMENT_NODE)
232         {
233           printf ("%s", node->name);
234           for (xmlNode *child = node->children; child; child = child->next)
235             if (child->type == XML_TEXT_NODE)
236               {
237                 putchar (' ');
238                 print_string (child->content);
239               }
240           putchar ('\n');
241         }
242
243       print_text (node->children);
244     }
245 }
246
247 static void
248 usage (void)
249 {
250   fprintf (stderr, "usage: parse-xml FILE.xml containment|attributes\n");
251   exit (1);
252 }
253
254 int
255 main (int argc, char **argv)
256 {
257   if (argc != 3)
258     usage ();
259
260   LIBXML_TEST_VERSION;
261
262   xmlDoc *doc = xmlReadFile(argv[1], NULL, XML_PARSE_NOBLANKS);
263   if (doc == NULL)
264     {
265       fprintf (stderr, "error: could not parse file %s\n", argv[1]);
266       exit (1);
267     }
268
269   xmlNode *root = xmlDocGetRootElement(doc);
270
271 #if 0
272   /* Limit what we look at to pageSetup node and below. */
273   root = find_page_setup(root);
274   if (!root)
275     return 0;
276   root->next = NULL;
277 #endif
278
279   if (!strcmp(argv[2], "parents"))
280     print_parents (root);
281   else if (!strcmp(argv[2], "containment"))
282     print_containment (root);
283   else if (!strcmp(argv[2], "attributes"))
284     print_attributes (root);
285   else if (!strcmp(argv[2], "cdata"))
286     print_cdata (root);
287   else if (!strcmp(argv[2], "text"))
288     print_text (root);
289   else if (!strncmp(argv[2], "element:", 8))
290     print_element (doc, root, argv[2] + 8);
291   else if (!strncmp(argv[2], "attr:", 5))
292     print_attribute (root, argv[2] + 5);
293   else if (!strcmp(argv[2], "labels"))
294     print_labels (root);
295   else
296     usage ();
297
298   xmlFreeDoc(doc);
299   xmlCleanupParser();
300
301   return 0;
302 }