]> mj.ucw.cz Git - libucw.git/blob - sherlock/xml/xml-test.c
XML: Split to several files, revised part of iface and
[libucw.git] / sherlock / xml / xml-test.c
1 /*
2  *      Sherlock Library -- A simple XML parser
3  *
4  *      (c) 2007 Pavel Charvat <pchar@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #include "sherlock/sherlock.h"
11 #include "sherlock/xml/xml.h"
12 #include "lib/getopt.h"
13 #include "lib/fastbuf.h"
14
15 #include <stdio.h>
16 #include <stdlib.h>
17
18 static char *shortopts = "sp" CF_SHORT_OPTS;
19 static struct option longopts[] = {
20   CF_LONG_OPTS
21   { "sax",      0, 0, 's' },
22   { "pull",     0, 0, 'p' },
23   { "dom",      0, 0, 'd' },
24   { NULL,       0, 0, 0 }
25 };
26
27 static void NONRET
28 usage(void)
29 {
30   fputs("\
31 Usage: xml-test [options] < in.xml\n\
32 \n\
33 Options:\n"
34 CF_USAGE
35 "\
36 -s, --pull  Test PULL interface\n\
37 -s, --sax   Test SAX interface\n\
38 -d, --dom   Test DOM interface\n\
39 \n", stderr);
40   exit(1);
41 }
42
43 static uns want_sax;
44 static uns want_pull;
45 static uns want_dom;
46 static struct fastbuf *out;
47
48 static char *
49 node_type(struct xml_node *node)
50 {
51   switch (node->type)
52     {
53       case XML_NODE_ELEM: return "element";
54       case XML_NODE_COMMENT: return "comment";
55       case XML_NODE_PI: return "pi";
56       case XML_NODE_CDATA: return "chars";
57       default: return "unknown";
58     }
59 }
60
61 static void
62 show_node(struct xml_node *node)
63 {
64   switch (node->type)
65     {
66       case XML_NODE_ELEM:
67         bprintf(out, " <%s>", node->name);
68         SLIST_FOR_EACH(struct xml_attr *, a, node->attrs)
69           bprintf(out, " %s='%s'", a->name, a->val);
70         bputc(out, '\n');
71         break;
72       case XML_NODE_COMMENT:
73         bprintf(out, " text='%s'\n", node->text);
74         break;
75       case XML_NODE_PI:
76         bprintf(out, " target=%s text='%s'\n", node->name, node->text);
77         break;
78       case XML_NODE_CDATA:
79         bprintf(out, " text='%s'\n", node->text);
80         break;
81       default:
82         bputc(out, '\n');
83     }
84 }
85
86 static void
87 show_tree(struct xml_node *node, uns level)
88 {
89   if (!node)
90     return;
91   bputs(out, "DOM:  ");
92   for (uns i = 0; i < level; i++)
93     bputs(out, "    ");
94   bputs(out, node_type(node));
95   show_node(node);
96   if (node->type == XML_NODE_ELEM)
97     CLIST_FOR_EACH(struct xml_node *, son, node->sons)
98       show_tree(son, level + 1);
99 }
100
101 static void
102 h_error(struct xml_context *ctx)
103 {
104   bprintf(out, "SAX:  %s at %u: %s\n", (ctx->err_code < XML_ERR_ERROR) ? "warn" : "error", xml_row(ctx), ctx->err_msg);
105 }
106
107 static void
108 h_document_start(struct xml_context *ctx UNUSED)
109 {
110   bputs(out, "SAX:  document_start\n");
111 }
112
113 static void
114 h_document_end(struct xml_context *ctx UNUSED)
115 {
116   bputs(out, "SAX:  document_end\n");
117 }
118
119 static void
120 h_xml_decl(struct xml_context *ctx)
121 {
122   bprintf(out, "SAX:  xml_decl version=%s standalone=%d\n", ctx->version_str, ctx->standalone);
123 }
124
125 static void
126 h_doctype_decl(struct xml_context *ctx)
127 {
128   bprintf(out, "SAX:  doctype_decl type=%s public='%s' system='%s' extsub=%d intsub=%d\n",
129     ctx->document_type, ctx->eid.public_id ? : "", ctx->eid.system_id ? : "",
130     !!(ctx->flags & XML_FLAG_HAS_EXTERNAL_SUBSET), !!(ctx->flags & XML_FLAG_HAS_INTERNAL_SUBSET));
131 }
132
133 static void
134 h_comment(struct xml_context *ctx)
135 {
136   bputs(out, "SAX:  comment");
137   show_node(ctx->node);
138 }
139
140 static void
141 h_pi(struct xml_context *ctx)
142 {
143   bprintf(out, "SAX:  pi");
144   show_node(ctx->node);
145 }
146
147 static void
148 h_element_start(struct xml_context *ctx)
149 {
150   bprintf(out, "SAX:  element_start");
151   show_node(ctx->node);
152 }
153
154 static void
155 h_element_end(struct xml_context *ctx)
156 {
157   bprintf(out, "SAX:  element_end </%s>\n", ctx->node->name);
158 }
159
160 static void
161 h_chars(struct xml_context *ctx)
162 {
163   bprintf(out, "SAX:  chars");
164   show_node(ctx->node);
165 }
166
167 int
168 main(int argc, char **argv)
169 {
170   int opt;
171   cf_def_file = NULL; // FIXME 
172   log_init(argv[0]);
173   while ((opt = cf_getopt(argc, argv, shortopts, longopts, NULL)) >= 0)
174     switch (opt)
175       {
176         case 's':
177           want_sax++;
178           break;
179         case 'p':
180           want_pull++;
181           break;
182         case 'd':
183           want_dom++;
184           break;
185         default:
186           usage();
187       }
188   if (optind != argc)
189     usage();
190
191   out = bfdopen_shared(1, 4096);
192   struct xml_context ctx;
193   xml_init(&ctx);
194   ctx.h_warn = ctx.h_error = ctx.h_fatal = h_error;
195   if (want_sax)
196     {
197       ctx.h_document_start = h_document_start;
198       ctx.h_document_end = h_document_end;
199       ctx.h_xml_decl = h_xml_decl;
200       ctx.h_doctype_decl = h_doctype_decl;
201       ctx.h_comment = h_comment;
202       ctx.h_pi = h_pi;
203       ctx.h_element_start = h_element_start;
204       ctx.h_element_end = h_element_end;
205       ctx.h_chars = h_chars;
206     }
207   if (want_pull)
208     ctx.want = XML_WANT_CHARS | XML_WANT_STAG | XML_WANT_ETAG | XML_WANT_COMMENT | XML_WANT_PI;
209   if (want_dom)
210     ctx.flags &= ~XML_DOM_FREE;
211   xml_set_source(&ctx, bfdopen_shared(0, 4096));
212   int state;
213   bprintf(out, "PULL: start\n");
214   while ((state = xml_next(&ctx)) >= 0 && state != XML_STATE_EOF)
215     switch (state)
216       {
217         case XML_STATE_CHARS:
218           bprintf(out, "PULL: chars");
219           show_node(ctx.node);
220           break;
221         case XML_STATE_STAG:
222           bprintf(out, "PULL: element_start");
223           show_node(ctx.node);
224           break;
225         case XML_STATE_ETAG:
226           bprintf(out, "PULL: element_end </%s>\n", ctx.node->name);
227           break;
228         case XML_STATE_COMMENT:
229           bprintf(out, "PULL: comment");
230           show_node(ctx.node);
231           break;
232         case XML_STATE_PI:
233           bprintf(out, "PULL: pi");
234           show_node(ctx.node);
235           break;
236 #if 0
237         case XML_STATE_CDATA:
238           bprintf(out, "PULL: cdata [%s]\n", ctx.node->text);
239           break;
240 #endif
241       }
242   if (state != XML_STATE_EOF)
243     bprintf(out, "PULL: fatal error\n");
244   else
245     bprintf(out, "PULL: eof\n");
246
247   if (want_dom)
248     show_tree(ctx.root, 0);
249
250   xml_cleanup(&ctx);
251   bclose(out);
252   return 0;
253 }