10a48773fSEric van Gyzen /* Read an XML document from standard input and print an element
20a48773fSEric van Gyzen outline on standard output.
30a48773fSEric van Gyzen Must be used with Expat compiled for UTF-8 output.
40a48773fSEric van Gyzen __ __ _
50a48773fSEric van Gyzen ___\ \/ /_ __ __ _| |_
60a48773fSEric van Gyzen / _ \\ /| '_ \ / _` | __|
70a48773fSEric van Gyzen | __// \| |_) | (_| | |_
80a48773fSEric van Gyzen \___/_/\_\ .__/ \__,_|\__|
90a48773fSEric van Gyzen |_| XML parser
105bb6a25fSPoul-Henning Kamp
11cc68614dSXin LI Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
12cc68614dSXin LI Copyright (c) 2001-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
13ac69e5d4SEric van Gyzen Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
14cc68614dSXin LI Copyright (c) 2005-2006 Karl Waclawek <karl@waclawek.net>
15*dc58b3fcSXin LI Copyright (c) 2016-2022 Sebastian Pipping <sebastian@pipping.org>
16cc68614dSXin LI Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
170a48773fSEric van Gyzen Licensed under the MIT license:
180a48773fSEric van Gyzen
190a48773fSEric van Gyzen Permission is hereby granted, free of charge, to any person obtaining
200a48773fSEric van Gyzen a copy of this software and associated documentation files (the
210a48773fSEric van Gyzen "Software"), to deal in the Software without restriction, including
220a48773fSEric van Gyzen without limitation the rights to use, copy, modify, merge, publish,
230a48773fSEric van Gyzen distribute, sublicense, and/or sell copies of the Software, and to permit
240a48773fSEric van Gyzen persons to whom the Software is furnished to do so, subject to the
250a48773fSEric van Gyzen following conditions:
260a48773fSEric van Gyzen
270a48773fSEric van Gyzen The above copyright notice and this permission notice shall be included
280a48773fSEric van Gyzen in all copies or substantial portions of the Software.
290a48773fSEric van Gyzen
300a48773fSEric van Gyzen THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
310a48773fSEric van Gyzen EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
320a48773fSEric van Gyzen MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
330a48773fSEric van Gyzen NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
340a48773fSEric van Gyzen DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
350a48773fSEric van Gyzen OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
360a48773fSEric van Gyzen USE OR OTHER DEALINGS IN THE SOFTWARE.
370a48773fSEric van Gyzen */
385bb6a25fSPoul-Henning Kamp
395bb6a25fSPoul-Henning Kamp #include <stdio.h>
405bb6a25fSPoul-Henning Kamp #include <expat.h>
415bb6a25fSPoul-Henning Kamp
42220ed979SColeman Kane #ifdef XML_LARGE_SIZE
43220ed979SColeman Kane # define XML_FMT_INT_MOD "ll"
44220ed979SColeman Kane #else
45220ed979SColeman Kane # define XML_FMT_INT_MOD "l"
46220ed979SColeman Kane #endif
47220ed979SColeman Kane
480a48773fSEric van Gyzen #ifdef XML_UNICODE_WCHAR_T
490a48773fSEric van Gyzen # define XML_FMT_STR "ls"
500a48773fSEric van Gyzen #else
510a48773fSEric van Gyzen # define XML_FMT_STR "s"
520a48773fSEric van Gyzen #endif
530a48773fSEric van Gyzen
54220ed979SColeman Kane static void XMLCALL
startElement(void * userData,const XML_Char * name,const XML_Char ** atts)55*dc58b3fcSXin LI startElement(void *userData, const XML_Char *name, const XML_Char **atts) {
565bb6a25fSPoul-Henning Kamp int i;
57*dc58b3fcSXin LI int *const depthPtr = (int *)userData;
585bb6a25fSPoul-Henning Kamp
59*dc58b3fcSXin LI for (i = 0; i < *depthPtr; i++)
605bb6a25fSPoul-Henning Kamp printf(" ");
615bb6a25fSPoul-Henning Kamp
62*dc58b3fcSXin LI printf("%" XML_FMT_STR, name);
635bb6a25fSPoul-Henning Kamp
64*dc58b3fcSXin LI for (i = 0; atts[i]; i += 2) {
65*dc58b3fcSXin LI printf(" %" XML_FMT_STR "='%" XML_FMT_STR "'", atts[i], atts[i + 1]);
665bb6a25fSPoul-Henning Kamp }
675bb6a25fSPoul-Henning Kamp
685bb6a25fSPoul-Henning Kamp printf("\n");
69*dc58b3fcSXin LI *depthPtr += 1;
705bb6a25fSPoul-Henning Kamp }
715bb6a25fSPoul-Henning Kamp
72220ed979SColeman Kane static void XMLCALL
endElement(void * userData,const XML_Char * name)73*dc58b3fcSXin LI endElement(void *userData, const XML_Char *name) {
74*dc58b3fcSXin LI int *const depthPtr = (int *)userData;
75*dc58b3fcSXin LI (void)name;
76be8aff81SXin LI
77*dc58b3fcSXin LI *depthPtr -= 1;
785bb6a25fSPoul-Henning Kamp }
795bb6a25fSPoul-Henning Kamp
805bb6a25fSPoul-Henning Kamp int
main(void)81*dc58b3fcSXin LI main(void) {
82*dc58b3fcSXin LI XML_Parser parser = XML_ParserCreate(NULL);
83*dc58b3fcSXin LI int done;
84*dc58b3fcSXin LI int depth = 0;
85be8aff81SXin LI
86*dc58b3fcSXin LI if (! parser) {
875bb6a25fSPoul-Henning Kamp fprintf(stderr, "Couldn't allocate memory for parser\n");
88*dc58b3fcSXin LI return 1;
895bb6a25fSPoul-Henning Kamp }
905bb6a25fSPoul-Henning Kamp
91*dc58b3fcSXin LI XML_SetUserData(parser, &depth);
92*dc58b3fcSXin LI XML_SetElementHandler(parser, startElement, endElement);
935bb6a25fSPoul-Henning Kamp
94*dc58b3fcSXin LI do {
95*dc58b3fcSXin LI void *const buf = XML_GetBuffer(parser, BUFSIZ);
96*dc58b3fcSXin LI if (! buf) {
97*dc58b3fcSXin LI fprintf(stderr, "Couldn't allocate memory for buffer\n");
98*dc58b3fcSXin LI XML_ParserFree(parser);
99*dc58b3fcSXin LI return 1;
100*dc58b3fcSXin LI }
1015bb6a25fSPoul-Henning Kamp
102*dc58b3fcSXin LI const size_t len = fread(buf, 1, BUFSIZ, stdin);
103*dc58b3fcSXin LI
1045bb6a25fSPoul-Henning Kamp if (ferror(stdin)) {
1055bb6a25fSPoul-Henning Kamp fprintf(stderr, "Read error\n");
106*dc58b3fcSXin LI XML_ParserFree(parser);
107*dc58b3fcSXin LI return 1;
1085bb6a25fSPoul-Henning Kamp }
109*dc58b3fcSXin LI
1105bb6a25fSPoul-Henning Kamp done = feof(stdin);
1115bb6a25fSPoul-Henning Kamp
112*dc58b3fcSXin LI if (XML_ParseBuffer(parser, (int)len, done) == XML_STATUS_ERROR) {
1130a48773fSEric van Gyzen fprintf(stderr,
1140a48773fSEric van Gyzen "Parse error at line %" XML_FMT_INT_MOD "u:\n%" XML_FMT_STR "\n",
115*dc58b3fcSXin LI XML_GetCurrentLineNumber(parser),
116*dc58b3fcSXin LI XML_ErrorString(XML_GetErrorCode(parser)));
117*dc58b3fcSXin LI XML_ParserFree(parser);
118*dc58b3fcSXin LI return 1;
1195bb6a25fSPoul-Henning Kamp }
120*dc58b3fcSXin LI } while (! done);
1215bb6a25fSPoul-Henning Kamp
122*dc58b3fcSXin LI XML_ParserFree(parser);
1235bb6a25fSPoul-Henning Kamp return 0;
1245bb6a25fSPoul-Henning Kamp }
125