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"
27 static char *shortopts = "spd" CF_SHORT_OPTS;
28 static struct option longopts[] = {
31 { "pull", 0, 0, 'p' },
33 { "dtd", 0, 0, WANT_PARSE_DTD },
34 { "hide-errors", 0, 0, WANT_HIDE_ERRORS },
35 { "unfold-cdata", 0, 0, WANT_UNFOLD_CDATA },
36 { "ignore-comments", 0, 0, WANT_IGNORE_COMMENTS },
37 { "ignore-pis", 0, 0, WANT_IGNORE_PIS },
45 Usage: xml-test [options] < input.xml\n\
50 -p, --pull Test PULL interface\n\
51 -s, --sax Test SAX interface\n\
52 -d, --dom Test DOM interface\n\
53 --dtd Enable parsing of DTD\n\
54 --hide-errors Hide warnings and error messages\n\
55 --unfold-cdata Unfold CDATA sections\n\
56 --ignore-comments Ignore processing instructions\n\
57 --ignore-pis Ignore comments\n\
65 static uns want_parse_dtd;
66 static uns want_hide_errors;
67 static uns want_unfold_cdata;
68 static uns want_ignore_comments;
69 static uns want_ignore_pis;
71 static struct fastbuf *out;
74 node_type(struct xml_node *node)
78 case XML_NODE_ELEM: return "element";
79 case XML_NODE_COMMENT: return "comment";
80 case XML_NODE_PI: return "pi";
81 case XML_NODE_CHARS: return "chars";
82 default: return "unknown";
87 show_node(struct xml_node *node)
92 bprintf(out, " <%s>", node->name);
93 XML_ATTR_FOR_EACH(a, node)
94 bprintf(out, " %s='%s'", a->name, a->val);
97 case XML_NODE_COMMENT:
98 bprintf(out, " text='%s'\n", node->text);
101 bprintf(out, " target=%s text='%s'\n", node->name, node->text);
104 bprintf(out, " text='%s'\n", node->text);
112 show_tree(struct xml_node *node, uns level)
117 for (uns i = 0; i < level; i++)
119 bputs(out, node_type(node));
121 if (node->type == XML_NODE_ELEM)
122 XML_NODE_FOR_EACH(son, node)
123 show_tree(son, level + 1);
127 h_error(struct xml_context *ctx)
129 bprintf(out, "SAX: %s at %u: %s\n", (ctx->err_code < XML_ERR_ERROR) ? "warn" : "error", xml_row(ctx), ctx->err_msg);
133 h_document_start(struct xml_context *ctx UNUSED)
135 bputs(out, "SAX: document_start\n");
139 h_document_end(struct xml_context *ctx UNUSED)
141 bputs(out, "SAX: document_end\n");
145 h_xml_decl(struct xml_context *ctx)
147 bprintf(out, "SAX: xml_decl version=%s standalone=%d\n", ctx->version_str, ctx->standalone);
151 h_doctype_decl(struct xml_context *ctx)
153 bprintf(out, "SAX: doctype_decl type=%s public='%s' system='%s' extsub=%d intsub=%d\n",
154 ctx->doctype, ctx->public_id ? : "", ctx->system_id ? : "",
155 !!(ctx->flags & XML_HAS_EXTERNAL_SUBSET), !!(ctx->flags & XML_HAS_INTERNAL_SUBSET));
159 h_comment(struct xml_context *ctx)
161 bputs(out, "SAX: comment");
162 show_node(ctx->node);
166 h_pi(struct xml_context *ctx)
168 bputs(out, "SAX: pi");
169 show_node(ctx->node);
173 h_stag(struct xml_context *ctx)
175 bputs(out, "SAX: stag");
176 show_node(ctx->node);
180 h_etag(struct xml_context *ctx)
182 bprintf(out, "SAX: etag </%s>\n", ctx->node->name);
186 h_chars(struct xml_context *ctx)
188 bputs(out, "SAX: chars");
189 show_node(ctx->node);
193 h_cdata(struct xml_context *ctx)
195 bputs(out, "SAX: cdata");
196 show_node(ctx->node);
200 h_dtd_start(struct xml_context *ctx UNUSED)
202 bputs(out, "SAX: dtd_start\n");
206 h_dtd_end(struct xml_context *ctx UNUSED)
208 bputs(out, "SAX: dtd_end\n");
212 main(int argc, char **argv)
217 while ((opt = cf_getopt(argc, argv, shortopts, longopts, NULL)) >= 0)
232 case WANT_HIDE_ERRORS:
235 case WANT_UNFOLD_CDATA:
238 case WANT_IGNORE_COMMENTS:
239 want_ignore_comments++;
241 case WANT_IGNORE_PIS:
250 out = bfdopen_shared(1, 4096);
251 struct xml_context ctx;
253 if (!want_hide_errors)
254 ctx.h_warn = ctx.h_error = ctx.h_fatal = h_error;
257 ctx.h_document_start = h_document_start;
258 ctx.h_document_end = h_document_end;
259 ctx.h_xml_decl = h_xml_decl;
260 ctx.h_doctype_decl = h_doctype_decl;
261 ctx.h_comment = h_comment;
265 ctx.h_chars = h_chars;
266 ctx.h_cdata = h_cdata;
267 ctx.h_dtd_start = h_dtd_start;
268 ctx.h_dtd_end = h_dtd_end;
271 ctx.flags |= XML_ALLOC_ALL;
273 ctx.flags |= XML_PARSE_DTD;
274 if (want_unfold_cdata)
275 ctx.flags |= XML_UNFOLD_CDATA;
276 if (want_ignore_comments)
277 ctx.flags &= ~(XML_REPORT_COMMENTS | XML_ALLOC_COMMENTS);
279 ctx.flags &= ~(XML_REPORT_PIS | XML_ALLOC_PIS);
280 xml_set_source(&ctx, bfdopen_shared(0, 4096));
281 bputs(out, "PULL: start\n");
284 ctx.pull = XML_PULL_CHARS | XML_PULL_CDATA | XML_PULL_STAG | XML_PULL_ETAG | XML_PULL_COMMENT | XML_PULL_PI;
286 while (state = xml_next(&ctx))
289 case XML_STATE_CHARS:
290 bputs(out, "PULL: chars");
293 case XML_STATE_CDATA:
294 bputs(out, "PULL: cdata");
298 bputs(out, "PULL: stag");
302 bprintf(out, "PULL: etag </%s>\n", ctx.node->name);
304 case XML_STATE_COMMENT:
305 bputs(out, "PULL: comment");
309 bputs(out, "PULL: pi");
313 bputs(out, "PULL: unknown\n");
320 bprintf(out, "PULL: fatal error at %u: %s\n", xml_row(&ctx), ctx.err_msg);
323 bputs(out, "PULL: eof\n");
325 show_tree(ctx.dom, 0);