11a3ddf8cSespie /* This is simple demonstration of how to use expat. This program
21a3ddf8cSespie reads an XML document from standard input and writes a line with
31a3ddf8cSespie the name of each element to standard output indenting child
41a3ddf8cSespie elements by one tab stop more than their parent element.
57d36914fSalek It must be used with Expat compiled for UTF-8 output.
62e724bc9Sbluhm __ __ _
72e724bc9Sbluhm ___\ \/ /_ __ __ _| |_
82e724bc9Sbluhm / _ \\ /| '_ \ / _` | __|
92e724bc9Sbluhm | __// \| |_) | (_| | |_
102e724bc9Sbluhm \___/_/\_\ .__/ \__,_|\__|
112e724bc9Sbluhm |_| XML parser
122e724bc9Sbluhm
132e724bc9Sbluhm Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
1408819b41Sbluhm Copyright (c) 2001-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
1508819b41Sbluhm Copyright (c) 2004-2006 Karl Waclawek <karl@waclawek.net>
16253fd6bfSbluhm Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
17*751a8f41Sbluhm Copyright (c) 2016-2022 Sebastian Pipping <sebastian@pipping.org>
1808819b41Sbluhm Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
1908819b41Sbluhm Copyright (c) 2019 Zhongyuan Zhou <zhouzhongyuan@huawei.com>
202e724bc9Sbluhm Licensed under the MIT license:
212e724bc9Sbluhm
222e724bc9Sbluhm Permission is hereby granted, free of charge, to any person obtaining
232e724bc9Sbluhm a copy of this software and associated documentation files (the
242e724bc9Sbluhm "Software"), to deal in the Software without restriction, including
252e724bc9Sbluhm without limitation the rights to use, copy, modify, merge, publish,
262e724bc9Sbluhm distribute, sublicense, and/or sell copies of the Software, and to permit
272e724bc9Sbluhm persons to whom the Software is furnished to do so, subject to the
282e724bc9Sbluhm following conditions:
292e724bc9Sbluhm
302e724bc9Sbluhm The above copyright notice and this permission notice shall be included
312e724bc9Sbluhm in all copies or substantial portions of the Software.
322e724bc9Sbluhm
332e724bc9Sbluhm THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
342e724bc9Sbluhm EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
352e724bc9Sbluhm MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
362e724bc9Sbluhm NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
372e724bc9Sbluhm DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
382e724bc9Sbluhm OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
392e724bc9Sbluhm USE OR OTHER DEALINGS IN THE SOFTWARE.
401a3ddf8cSespie */
411a3ddf8cSespie
421a3ddf8cSespie #include <stdio.h>
432feb5d2aSbluhm #include <expat.h>
44b26ab0f8Smatthieu
457d36914fSalek #ifdef XML_LARGE_SIZE
467d36914fSalek # define XML_FMT_INT_MOD "ll"
477d36914fSalek #else
487d36914fSalek # define XML_FMT_INT_MOD "l"
497d36914fSalek #endif
507d36914fSalek
519b8e2351Sbluhm #ifdef XML_UNICODE_WCHAR_T
529b8e2351Sbluhm # define XML_FMT_STR "ls"
539b8e2351Sbluhm #else
549b8e2351Sbluhm # define XML_FMT_STR "s"
559b8e2351Sbluhm #endif
569b8e2351Sbluhm
577d36914fSalek static void XMLCALL
startElement(void * userData,const XML_Char * name,const XML_Char ** atts)5828ce3119Sbluhm startElement(void *userData, const XML_Char *name, const XML_Char **atts) {
591a3ddf8cSespie int i;
60*751a8f41Sbluhm int *const depthPtr = (int *)userData;
612feb5d2aSbluhm (void)atts;
622feb5d2aSbluhm
631a3ddf8cSespie for (i = 0; i < *depthPtr; i++)
641a3ddf8cSespie putchar('\t');
659b8e2351Sbluhm printf("%" XML_FMT_STR "\n", name);
661a3ddf8cSespie *depthPtr += 1;
671a3ddf8cSespie }
681a3ddf8cSespie
697d36914fSalek static void XMLCALL
endElement(void * userData,const XML_Char * name)7028ce3119Sbluhm endElement(void *userData, const XML_Char *name) {
71*751a8f41Sbluhm int *const depthPtr = (int *)userData;
722feb5d2aSbluhm (void)name;
732feb5d2aSbluhm
741a3ddf8cSespie *depthPtr -= 1;
751a3ddf8cSespie }
761a3ddf8cSespie
771a3ddf8cSespie int
main(void)78*751a8f41Sbluhm main(void) {
791a3ddf8cSespie XML_Parser parser = XML_ParserCreate(NULL);
801a3ddf8cSespie int done;
811a3ddf8cSespie int depth = 0;
82*751a8f41Sbluhm
83*751a8f41Sbluhm if (! parser) {
84*751a8f41Sbluhm fprintf(stderr, "Couldn't allocate memory for parser\n");
85*751a8f41Sbluhm return 1;
86*751a8f41Sbluhm }
872feb5d2aSbluhm
881a3ddf8cSespie XML_SetUserData(parser, &depth);
891a3ddf8cSespie XML_SetElementHandler(parser, startElement, endElement);
90*751a8f41Sbluhm
911a3ddf8cSespie do {
92*751a8f41Sbluhm void *const buf = XML_GetBuffer(parser, BUFSIZ);
93*751a8f41Sbluhm if (! buf) {
94*751a8f41Sbluhm fprintf(stderr, "Couldn't allocate memory for buffer\n");
95*751a8f41Sbluhm XML_ParserFree(parser);
96*751a8f41Sbluhm return 1;
97*751a8f41Sbluhm }
98*751a8f41Sbluhm
99*751a8f41Sbluhm const size_t len = fread(buf, 1, BUFSIZ, stdin);
100*751a8f41Sbluhm
101*751a8f41Sbluhm if (ferror(stdin)) {
102*751a8f41Sbluhm fprintf(stderr, "Read error\n");
103*751a8f41Sbluhm XML_ParserFree(parser);
104*751a8f41Sbluhm return 1;
105*751a8f41Sbluhm }
106*751a8f41Sbluhm
107*751a8f41Sbluhm done = feof(stdin);
108*751a8f41Sbluhm
109*751a8f41Sbluhm if (XML_ParseBuffer(parser, (int)len, done) == XML_STATUS_ERROR) {
110*751a8f41Sbluhm fprintf(stderr,
111*751a8f41Sbluhm "Parse error at line %" XML_FMT_INT_MOD "u:\n%" XML_FMT_STR "\n",
112*751a8f41Sbluhm XML_GetCurrentLineNumber(parser),
113*751a8f41Sbluhm XML_ErrorString(XML_GetErrorCode(parser)));
11428ce3119Sbluhm XML_ParserFree(parser);
1151a3ddf8cSespie return 1;
1161a3ddf8cSespie }
1171a3ddf8cSespie } while (! done);
118*751a8f41Sbluhm
1191a3ddf8cSespie XML_ParserFree(parser);
1201a3ddf8cSespie return 0;
1211a3ddf8cSespie }
122