2 * Sherlock Library -- A simple XML parser
4 * (c) 2007 Pavel Charvat <pchar@ucw.cz>
6 * This software may be freely distributed and used according to the terms
7 * of the GNU Lesser General Public License.
10 #include "sherlock/sherlock.h"
11 #include "sherlock/xml/xml.h"
12 #include "lib/getopt.h"
13 #include "lib/fastbuf.h"
26 static char *shortopts = "spd" CF_SHORT_OPTS;
27 static struct option longopts[] = {
30 { "pull", 0, 0, 'p' },
32 { "hide-errors", 0, 0, WANT_HIDE_ERRORS },
33 { "unfold-cdata", 0, 0, WANT_UNFOLD_CDATA },
34 { "ignore-comments", 0, 0, WANT_IGNORE_COMMENTS },
35 { "ignore-pis", 0, 0, WANT_IGNORE_PIS },
43 Usage: xml-test [options] < input.xml\n\
48 -s, --pull Test PULL interface\n\
49 -s, --sax Test SAX interface\n\
50 -d, --dom Test DOM interface\n\
51 --hide-errors Hide warnings and error messages\n\
52 --unfold-cdata Unfold CDATA sections\n\
53 --ignore-comments Ignore processing instructions\n\
54 --ignore-pis Ignore comments\n\
62 static uns want_hide_errors;
63 static uns want_unfold_cdata;
64 static uns want_ignore_comments;
65 static uns want_ignore_pis;
67 static struct fastbuf *out;
70 node_type(struct xml_node *node)
74 case XML_NODE_ELEM: return "element";
75 case XML_NODE_COMMENT: return "comment";
76 case XML_NODE_PI: return "pi";
77 case XML_NODE_CHARS: return "chars";
78 default: return "unknown";
83 show_node(struct xml_node *node)
88 bprintf(out, " <%s>", node->name);
89 XML_ATTR_FOR_EACH(a, node)
90 bprintf(out, " %s='%s'", a->name, a->val);
93 case XML_NODE_COMMENT:
94 bprintf(out, " text='%s'\n", node->text);
97 bprintf(out, " target=%s text='%s'\n", node->name, node->text);
100 bprintf(out, " text='%s'\n", node->text);
108 show_tree(struct xml_node *node, uns level)
113 for (uns i = 0; i < level; i++)
115 bputs(out, node_type(node));
117 if (node->type == XML_NODE_ELEM)
118 XML_NODE_FOR_EACH(son, node)
119 show_tree(son, level + 1);
123 h_error(struct xml_context *ctx)
125 bprintf(out, "SAX: %s at %u: %s\n", (ctx->err_code < XML_ERR_ERROR) ? "warn" : "error", xml_row(ctx), ctx->err_msg);
129 h_document_start(struct xml_context *ctx UNUSED)
131 bputs(out, "SAX: document_start\n");
135 h_document_end(struct xml_context *ctx UNUSED)
137 bputs(out, "SAX: document_end\n");
141 h_xml_decl(struct xml_context *ctx)
143 bprintf(out, "SAX: xml_decl version=%s standalone=%d\n", ctx->version_str, ctx->standalone);
147 h_doctype_decl(struct xml_context *ctx)
149 bprintf(out, "SAX: doctype_decl type=%s public='%s' system='%s' extsub=%d intsub=%d\n",
150 ctx->doctype, ctx->public_id ? : "", ctx->system_id ? : "",
151 !!(ctx->flags & XML_HAS_EXTERNAL_SUBSET), !!(ctx->flags & XML_HAS_INTERNAL_SUBSET));
155 h_comment(struct xml_context *ctx)
157 bputs(out, "SAX: comment");
158 show_node(ctx->node);
162 h_pi(struct xml_context *ctx)
164 bputs(out, "SAX: pi");
165 show_node(ctx->node);
169 h_stag(struct xml_context *ctx)
171 bputs(out, "SAX: stag");
172 show_node(ctx->node);
176 h_etag(struct xml_context *ctx)
178 bprintf(out, "SAX: etag </%s>\n", ctx->node->name);
182 h_chars(struct xml_context *ctx)
184 bputs(out, "SAX: chars");
185 show_node(ctx->node);
189 h_cdata(struct xml_context *ctx)
191 bputs(out, "SAX: cdata");
192 show_node(ctx->node);
196 h_dtd_start(struct xml_context *ctx UNUSED)
198 bputs(out, "SAX: dtd_start\n");
202 h_dtd_end(struct xml_context *ctx UNUSED)
204 bputs(out, "SAX: dtd_end\n");
208 main(int argc, char **argv)
213 while ((opt = cf_getopt(argc, argv, shortopts, longopts, NULL)) >= 0)
225 case WANT_HIDE_ERRORS:
228 case WANT_UNFOLD_CDATA:
231 case WANT_IGNORE_COMMENTS:
232 want_ignore_comments++;
234 case WANT_IGNORE_PIS:
243 out = bfdopen_shared(1, 4096);
244 struct xml_context ctx;
246 if (!want_hide_errors)
247 ctx.h_warn = ctx.h_error = ctx.h_fatal = h_error;
250 ctx.h_document_start = h_document_start;
251 ctx.h_document_end = h_document_end;
252 ctx.h_xml_decl = h_xml_decl;
253 ctx.h_doctype_decl = h_doctype_decl;
254 ctx.h_comment = h_comment;
258 ctx.h_chars = h_chars;
259 ctx.h_cdata = h_cdata;
260 ctx.h_dtd_start = h_dtd_start;
261 ctx.h_dtd_end = h_dtd_end;
264 ctx.flags |= XML_ALLOC_ALL;
265 if (want_unfold_cdata)
266 ctx.flags |= XML_UNFOLD_CDATA;
267 if (want_ignore_comments)
268 ctx.flags &= ~(XML_REPORT_COMMENTS | XML_ALLOC_COMMENTS);
270 ctx.flags &= ~(XML_REPORT_PIS | XML_ALLOC_PIS);
271 xml_set_source(&ctx, bfdopen_shared(0, 4096));
272 bputs(out, "PULL: start\n");
275 ctx.pull = XML_PULL_CHARS | XML_PULL_CDATA | XML_PULL_STAG | XML_PULL_ETAG | XML_PULL_COMMENT | XML_PULL_PI;
277 while (state = xml_next(&ctx))
280 case XML_STATE_CHARS:
281 bputs(out, "PULL: chars");
284 case XML_STATE_CDATA:
285 bputs(out, "PULL: cdata");
289 bputs(out, "PULL: stag");
293 bprintf(out, "PULL: etag </%s>\n", ctx.node->name);
295 case XML_STATE_COMMENT:
296 bputs(out, "PULL: comment");
300 bputs(out, "PULL: pi");
304 bputs(out, "PULL: unknown\n");
311 bprintf(out, "PULL: fatal error at %u: %s\n", xml_row(&ctx), ctx.err_msg);
314 bputs(out, "PULL: eof\n");
316 show_tree(ctx.root, 0);