xmlwf.c revision 104349
1/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
2   See the file COPYING for copying permission.
3*/
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <stddef.h>
8#include <string.h>
9
10#include "expat.h"
11#include "codepage.h"
12#include "xmlfile.h"
13#include "xmltchar.h"
14
15#ifdef _MSC_VER
16#include <crtdbg.h>
17#endif
18
19/* This ensures proper sorting. */
20
21#define NSSEP T('\001')
22
23static void
24characterData(void *userData, const XML_Char *s, int len)
25{
26  FILE *fp = userData;
27  for (; len > 0; --len, ++s) {
28    switch (*s) {
29    case T('&'):
30      fputts(T("&amp;"), fp);
31      break;
32    case T('<'):
33      fputts(T("&lt;"), fp);
34      break;
35    case T('>'):
36      fputts(T("&gt;"), fp);
37      break;
38#ifdef W3C14N
39    case 13:
40      fputts(T("&#xD;"), fp);
41      break;
42#else
43    case T('"'):
44      fputts(T("&quot;"), fp);
45      break;
46    case 9:
47    case 10:
48    case 13:
49      ftprintf(fp, T("&#%d;"), *s);
50      break;
51#endif
52    default:
53      puttc(*s, fp);
54      break;
55    }
56  }
57}
58
59static void
60attributeValue(FILE *fp, const XML_Char *s)
61{
62  puttc(T('='), fp);
63  puttc(T('"'), fp);
64  for (;;) {
65    switch (*s) {
66    case 0:
67    case NSSEP:
68      puttc(T('"'), fp);
69      return;
70    case T('&'):
71      fputts(T("&amp;"), fp);
72      break;
73    case T('<'):
74      fputts(T("&lt;"), fp);
75      break;
76    case T('"'):
77      fputts(T("&quot;"), fp);
78      break;
79#ifdef W3C14N
80    case 9:
81      fputts(T("&#x9;"), fp);
82      break;
83    case 10:
84      fputts(T("&#xA;"), fp);
85      break;
86    case 13:
87      fputts(T("&#xD;"), fp);
88      break;
89#else
90    case T('>'):
91      fputts(T("&gt;"), fp);
92      break;
93    case 9:
94    case 10:
95    case 13:
96      ftprintf(fp, T("&#%d;"), *s);
97      break;
98#endif
99    default:
100      puttc(*s, fp);
101      break;
102    }
103    s++;
104  }
105}
106
107/* Lexicographically comparing UTF-8 encoded attribute values,
108is equivalent to lexicographically comparing based on the character number. */
109
110static int
111attcmp(const void *att1, const void *att2)
112{
113  return tcscmp(*(const XML_Char **)att1, *(const XML_Char **)att2);
114}
115
116static void
117startElement(void *userData, const XML_Char *name, const XML_Char **atts)
118{
119  int nAtts;
120  const XML_Char **p;
121  FILE *fp = userData;
122  puttc(T('<'), fp);
123  fputts(name, fp);
124
125  p = atts;
126  while (*p)
127    ++p;
128  nAtts = (p - atts) >> 1;
129  if (nAtts > 1)
130    qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, attcmp);
131  while (*atts) {
132    puttc(T(' '), fp);
133    fputts(*atts++, fp);
134    attributeValue(fp, *atts);
135    atts++;
136  }
137  puttc(T('>'), fp);
138}
139
140static void
141endElement(void *userData, const XML_Char *name)
142{
143  FILE *fp = userData;
144  puttc(T('<'), fp);
145  puttc(T('/'), fp);
146  fputts(name, fp);
147  puttc(T('>'), fp);
148}
149
150static int
151nsattcmp(const void *p1, const void *p2)
152{
153  const XML_Char *att1 = *(const XML_Char **)p1;
154  const XML_Char *att2 = *(const XML_Char **)p2;
155  int sep1 = (tcsrchr(att1, NSSEP) != 0);
156  int sep2 = (tcsrchr(att1, NSSEP) != 0);
157  if (sep1 != sep2)
158    return sep1 - sep2;
159  return tcscmp(att1, att2);
160}
161
162static void
163startElementNS(void *userData, const XML_Char *name, const XML_Char **atts)
164{
165  int nAtts;
166  int nsi;
167  const XML_Char **p;
168  FILE *fp = userData;
169  const XML_Char *sep;
170  puttc(T('<'), fp);
171
172  sep = tcsrchr(name, NSSEP);
173  if (sep) {
174    fputts(T("n1:"), fp);
175    fputts(sep + 1, fp);
176    fputts(T(" xmlns:n1"), fp);
177    attributeValue(fp, name);
178    nsi = 2;
179  }
180  else {
181    fputts(name, fp);
182    nsi = 1;
183  }
184
185  p = atts;
186  while (*p)
187    ++p;
188  nAtts = (p - atts) >> 1;
189  if (nAtts > 1)
190    qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, nsattcmp);
191  while (*atts) {
192    name = *atts++;
193    sep = tcsrchr(name, NSSEP);
194    puttc(T(' '), fp);
195    if (sep) {
196      ftprintf(fp, T("n%d:"), nsi);
197      fputts(sep + 1, fp);
198    }
199    else
200      fputts(name, fp);
201    attributeValue(fp, *atts);
202    if (sep) {
203      ftprintf(fp, T(" xmlns:n%d"), nsi++);
204      attributeValue(fp, name);
205    }
206    atts++;
207  }
208  puttc(T('>'), fp);
209}
210
211static void
212endElementNS(void *userData, const XML_Char *name)
213{
214  FILE *fp = userData;
215  const XML_Char *sep;
216  puttc(T('<'), fp);
217  puttc(T('/'), fp);
218  sep = tcsrchr(name, NSSEP);
219  if (sep) {
220    fputts(T("n1:"), fp);
221    fputts(sep + 1, fp);
222  }
223  else
224    fputts(name, fp);
225  puttc(T('>'), fp);
226}
227
228#ifndef W3C14N
229
230static void
231processingInstruction(void *userData, const XML_Char *target,
232                      const XML_Char *data)
233{
234  FILE *fp = userData;
235  puttc(T('<'), fp);
236  puttc(T('?'), fp);
237  fputts(target, fp);
238  puttc(T(' '), fp);
239  fputts(data, fp);
240  puttc(T('?'), fp);
241  puttc(T('>'), fp);
242}
243
244#endif /* not W3C14N */
245
246static void
247defaultCharacterData(void *userData, const XML_Char *s, int len)
248{
249  XML_DefaultCurrent((XML_Parser) userData);
250}
251
252static void
253defaultStartElement(void *userData, const XML_Char *name,
254                    const XML_Char **atts)
255{
256  XML_DefaultCurrent((XML_Parser) userData);
257}
258
259static void
260defaultEndElement(void *userData, const XML_Char *name)
261{
262  XML_DefaultCurrent((XML_Parser) userData);
263}
264
265static void
266defaultProcessingInstruction(void *userData, const XML_Char *target,
267                             const XML_Char *data)
268{
269  XML_DefaultCurrent((XML_Parser) userData);
270}
271
272static void
273nopCharacterData(void *userData, const XML_Char *s, int len)
274{
275}
276
277static void
278nopStartElement(void *userData, const XML_Char *name, const XML_Char **atts)
279{
280}
281
282static void
283nopEndElement(void *userData, const XML_Char *name)
284{
285}
286
287static void
288nopProcessingInstruction(void *userData, const XML_Char *target,
289                         const XML_Char *data)
290{
291}
292
293static void
294markup(void *userData, const XML_Char *s, int len)
295{
296  FILE *fp = XML_GetUserData((XML_Parser) userData);
297  for (; len > 0; --len, ++s)
298    puttc(*s, fp);
299}
300
301static void
302metaLocation(XML_Parser parser)
303{
304  const XML_Char *uri = XML_GetBase(parser);
305  if (uri)
306    ftprintf(XML_GetUserData(parser), T(" uri=\"%s\""), uri);
307  ftprintf(XML_GetUserData(parser),
308           T(" byte=\"%ld\" nbytes=\"%d\" line=\"%d\" col=\"%d\""),
309           XML_GetCurrentByteIndex(parser),
310           XML_GetCurrentByteCount(parser),
311           XML_GetCurrentLineNumber(parser),
312           XML_GetCurrentColumnNumber(parser));
313}
314
315static void
316metaStartDocument(void *userData)
317{
318  fputts(T("<document>\n"), XML_GetUserData((XML_Parser) userData));
319}
320
321static void
322metaEndDocument(void *userData)
323{
324  fputts(T("</document>\n"), XML_GetUserData((XML_Parser) userData));
325}
326
327static void
328metaStartElement(void *userData, const XML_Char *name,
329                 const XML_Char **atts)
330{
331  XML_Parser parser = (XML_Parser) userData;
332  FILE *fp = XML_GetUserData(parser);
333  const XML_Char **specifiedAttsEnd
334    = atts + XML_GetSpecifiedAttributeCount(parser);
335  const XML_Char **idAttPtr;
336  int idAttIndex = XML_GetIdAttributeIndex(parser);
337  if (idAttIndex < 0)
338    idAttPtr = 0;
339  else
340    idAttPtr = atts + idAttIndex;
341
342  ftprintf(fp, T("<starttag name=\"%s\""), name);
343  metaLocation(parser);
344  if (*atts) {
345    fputts(T(">\n"), fp);
346    do {
347      ftprintf(fp, T("<attribute name=\"%s\" value=\""), atts[0]);
348      characterData(fp, atts[1], tcslen(atts[1]));
349      if (atts >= specifiedAttsEnd)
350        fputts(T("\" defaulted=\"yes\"/>\n"), fp);
351      else if (atts == idAttPtr)
352        fputts(T("\" id=\"yes\"/>\n"), fp);
353      else
354        fputts(T("\"/>\n"), fp);
355    } while (*(atts += 2));
356    fputts(T("</starttag>\n"), fp);
357  }
358  else
359    fputts(T("/>\n"), fp);
360}
361
362static void
363metaEndElement(void *userData, const XML_Char *name)
364{
365  XML_Parser parser = (XML_Parser) userData;
366  FILE *fp = XML_GetUserData(parser);
367  ftprintf(fp, T("<endtag name=\"%s\""), name);
368  metaLocation(parser);
369  fputts(T("/>\n"), fp);
370}
371
372static void
373metaProcessingInstruction(void *userData, const XML_Char *target,
374                          const XML_Char *data)
375{
376  XML_Parser parser = (XML_Parser) userData;
377  FILE *fp = XML_GetUserData(parser);
378  ftprintf(fp, T("<pi target=\"%s\" data=\""), target);
379  characterData(fp, data, tcslen(data));
380  puttc(T('"'), fp);
381  metaLocation(parser);
382  fputts(T("/>\n"), fp);
383}
384
385static void
386metaComment(void *userData, const XML_Char *data)
387{
388  XML_Parser parser = (XML_Parser) userData;
389  FILE *fp = XML_GetUserData(parser);
390  fputts(T("<comment data=\""), fp);
391  characterData(fp, data, tcslen(data));
392  puttc(T('"'), fp);
393  metaLocation(parser);
394  fputts(T("/>\n"), fp);
395}
396
397static void
398metaStartCdataSection(void *userData)
399{
400  XML_Parser parser = (XML_Parser) userData;
401  FILE *fp = XML_GetUserData(parser);
402  fputts(T("<startcdata"), fp);
403  metaLocation(parser);
404  fputts(T("/>\n"), fp);
405}
406
407static void
408metaEndCdataSection(void *userData)
409{
410  XML_Parser parser = (XML_Parser) userData;
411  FILE *fp = XML_GetUserData(parser);
412  fputts(T("<endcdata"), fp);
413  metaLocation(parser);
414  fputts(T("/>\n"), fp);
415}
416
417static void
418metaCharacterData(void *userData, const XML_Char *s, int len)
419{
420  XML_Parser parser = (XML_Parser) userData;
421  FILE *fp = XML_GetUserData(parser);
422  fputts(T("<chars str=\""), fp);
423  characterData(fp, s, len);
424  puttc(T('"'), fp);
425  metaLocation(parser);
426  fputts(T("/>\n"), fp);
427}
428
429static void
430metaStartDoctypeDecl(void *userData,
431                     const XML_Char *doctypeName,
432                     const XML_Char *sysid,
433                     const XML_Char *pubid,
434                     int has_internal_subset)
435{
436  XML_Parser parser = (XML_Parser) userData;
437  FILE *fp = XML_GetUserData(parser);
438  ftprintf(fp, T("<startdoctype name=\"%s\""), doctypeName);
439  metaLocation(parser);
440  fputts(T("/>\n"), fp);
441}
442
443static void
444metaEndDoctypeDecl(void *userData)
445{
446  XML_Parser parser = (XML_Parser) userData;
447  FILE *fp = XML_GetUserData(parser);
448  fputts(T("<enddoctype"), fp);
449  metaLocation(parser);
450  fputts(T("/>\n"), fp);
451}
452
453static void
454metaNotationDecl(void *userData,
455                 const XML_Char *notationName,
456                 const XML_Char *base,
457                 const XML_Char *systemId,
458                 const XML_Char *publicId)
459{
460  XML_Parser parser = (XML_Parser) userData;
461  FILE *fp = XML_GetUserData(parser);
462  ftprintf(fp, T("<notation name=\"%s\""), notationName);
463  if (publicId)
464    ftprintf(fp, T(" public=\"%s\""), publicId);
465  if (systemId) {
466    fputts(T(" system=\""), fp);
467    characterData(fp, systemId, tcslen(systemId));
468    puttc(T('"'), fp);
469  }
470  metaLocation(parser);
471  fputts(T("/>\n"), fp);
472}
473
474
475static void
476metaEntityDecl(void *userData,
477               const XML_Char *entityName,
478               int  is_param,
479               const XML_Char *value,
480               int  value_length,
481               const XML_Char *base,
482               const XML_Char *systemId,
483               const XML_Char *publicId,
484               const XML_Char *notationName)
485{
486  XML_Parser parser = (XML_Parser) userData;
487  FILE *fp = XML_GetUserData(parser);
488
489  if (value) {
490    ftprintf(fp, T("<entity name=\"%s\""), entityName);
491    metaLocation(parser);
492    puttc(T('>'), fp);
493    characterData(fp, value, value_length);
494    fputts(T("</entity/>\n"), fp);
495  }
496  else if (notationName) {
497    ftprintf(fp, T("<entity name=\"%s\""), entityName);
498    if (publicId)
499      ftprintf(fp, T(" public=\"%s\""), publicId);
500    fputts(T(" system=\""), fp);
501    characterData(fp, systemId, tcslen(systemId));
502    puttc(T('"'), fp);
503    ftprintf(fp, T(" notation=\"%s\""), notationName);
504    metaLocation(parser);
505    fputts(T("/>\n"), fp);
506  }
507  else {
508    ftprintf(fp, T("<entity name=\"%s\""), entityName);
509    if (publicId)
510      ftprintf(fp, T(" public=\"%s\""), publicId);
511    fputts(T(" system=\""), fp);
512    characterData(fp, systemId, tcslen(systemId));
513    puttc(T('"'), fp);
514    metaLocation(parser);
515    fputts(T("/>\n"), fp);
516  }
517}
518
519static void
520metaStartNamespaceDecl(void *userData,
521                       const XML_Char *prefix,
522                       const XML_Char *uri)
523{
524  XML_Parser parser = (XML_Parser) userData;
525  FILE *fp = XML_GetUserData(parser);
526  fputts(T("<startns"), fp);
527  if (prefix)
528    ftprintf(fp, T(" prefix=\"%s\""), prefix);
529  if (uri) {
530    fputts(T(" ns=\""), fp);
531    characterData(fp, uri, tcslen(uri));
532    fputts(T("\"/>\n"), fp);
533  }
534  else
535    fputts(T("/>\n"), fp);
536}
537
538static void
539metaEndNamespaceDecl(void *userData, const XML_Char *prefix)
540{
541  XML_Parser parser = (XML_Parser) userData;
542  FILE *fp = XML_GetUserData(parser);
543  if (!prefix)
544    fputts(T("<endns/>\n"), fp);
545  else
546    ftprintf(fp, T("<endns prefix=\"%s\"/>\n"), prefix);
547}
548
549static int
550unknownEncodingConvert(void *data, const char *p)
551{
552  return codepageConvert(*(int *)data, p);
553}
554
555static int
556unknownEncoding(void *userData, const XML_Char *name, XML_Encoding *info)
557{
558  int cp;
559  static const XML_Char prefixL[] = T("windows-");
560  static const XML_Char prefixU[] = T("WINDOWS-");
561  int i;
562
563  for (i = 0; prefixU[i]; i++)
564    if (name[i] != prefixU[i] && name[i] != prefixL[i])
565      return 0;
566
567  cp = 0;
568  for (; name[i]; i++) {
569    static const XML_Char digits[] = T("0123456789");
570    const XML_Char *s = tcschr(digits, name[i]);
571    if (!s)
572      return 0;
573    cp *= 10;
574    cp += s - digits;
575    if (cp >= 0x10000)
576      return 0;
577  }
578  if (!codepageMap(cp, info->map))
579    return 0;
580  info->convert = unknownEncodingConvert;
581  /* We could just cast the code page integer to a void *,
582  and avoid the use of release. */
583  info->release = free;
584  info->data = malloc(sizeof(int));
585  if (!info->data)
586    return 0;
587  *(int *)info->data = cp;
588  return 1;
589}
590
591static int
592notStandalone(void *userData)
593{
594  return 0;
595}
596
597static void
598showVersion(XML_Char *prog)
599{
600  XML_Char *s = prog;
601  XML_Char ch;
602  const XML_Feature *features = XML_GetFeatureList();
603  while ((ch = *s) != 0) {
604    if (ch == '/'
605#ifdef WIN32
606        || ch == '\\'
607#endif
608        )
609      prog = s + 1;
610    ++s;
611  }
612  ftprintf(stdout, T("%s using %s\n"), prog, XML_ExpatVersion());
613  if (features != NULL && features[0].feature != XML_FEATURE_END) {
614    int i = 1;
615    ftprintf(stdout, T("%s"), features[0].name);
616    if (features[0].value)
617      ftprintf(stdout, T("=%ld"), features[0].value);
618    while (features[i].feature != XML_FEATURE_END) {
619      ftprintf(stdout, T(", %s"), features[i].name);
620      if (features[i].value)
621        ftprintf(stdout, T("=%ld"), features[i].value);
622      ++i;
623    }
624    ftprintf(stdout, T("\n"));
625  }
626}
627
628static void
629usage(const XML_Char *prog, int rc)
630{
631  ftprintf(stderr,
632           T("usage: %s [-n] [-p] [-r] [-s] [-w] [-x] [-d output-dir] "
633             "[-e encoding] file ...\n"), prog);
634  exit(rc);
635}
636
637int
638tmain(int argc, XML_Char **argv)
639{
640  int i, j;
641  const XML_Char *outputDir = NULL;
642  const XML_Char *encoding = NULL;
643  unsigned processFlags = XML_MAP_FILE;
644  int windowsCodePages = 0;
645  int outputType = 0;
646  int useNamespaces = 0;
647  int requireStandalone = 0;
648  int paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
649  int useStdin = 0;
650
651#ifdef _MSC_VER
652  _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
653#endif
654
655  i = 1;
656  j = 0;
657  while (i < argc) {
658    if (j == 0) {
659      if (argv[i][0] != T('-'))
660        break;
661      if (argv[i][1] == T('-') && argv[i][2] == T('\0')) {
662        i++;
663        break;
664      }
665      j++;
666    }
667    switch (argv[i][j]) {
668    case T('r'):
669      processFlags &= ~XML_MAP_FILE;
670      j++;
671      break;
672    case T('s'):
673      requireStandalone = 1;
674      j++;
675      break;
676    case T('n'):
677      useNamespaces = 1;
678      j++;
679      break;
680    case T('p'):
681      paramEntityParsing = XML_PARAM_ENTITY_PARSING_ALWAYS;
682      /* fall through */
683    case T('x'):
684      processFlags |= XML_EXTERNAL_ENTITIES;
685      j++;
686      break;
687    case T('w'):
688      windowsCodePages = 1;
689      j++;
690      break;
691    case T('m'):
692      outputType = 'm';
693      j++;
694      break;
695    case T('c'):
696      outputType = 'c';
697      useNamespaces = 0;
698      j++;
699      break;
700    case T('t'):
701      outputType = 't';
702      j++;
703      break;
704    case T('d'):
705      if (argv[i][j + 1] == T('\0')) {
706        if (++i == argc)
707          usage(argv[0], 2);
708        outputDir = argv[i];
709      }
710      else
711        outputDir = argv[i] + j + 1;
712      i++;
713      j = 0;
714      break;
715    case T('e'):
716      if (argv[i][j + 1] == T('\0')) {
717        if (++i == argc)
718          usage(argv[0], 2);
719        encoding = argv[i];
720      }
721      else
722        encoding = argv[i] + j + 1;
723      i++;
724      j = 0;
725      break;
726    case T('h'):
727      usage(argv[0], 0);
728      return 0;
729    case T('v'):
730      showVersion(argv[0]);
731      return 0;
732    case T('\0'):
733      if (j > 1) {
734        i++;
735        j = 0;
736        break;
737      }
738      /* fall through */
739    default:
740      usage(argv[0], 2);
741    }
742  }
743  if (i == argc) {
744    useStdin = 1;
745    processFlags &= ~XML_MAP_FILE;
746    i--;
747  }
748  for (; i < argc; i++) {
749    FILE *fp = 0;
750    XML_Char *outName = 0;
751    int result;
752    XML_Parser parser;
753    if (useNamespaces)
754      parser = XML_ParserCreateNS(encoding, NSSEP);
755    else
756      parser = XML_ParserCreate(encoding);
757    if (requireStandalone)
758      XML_SetNotStandaloneHandler(parser, notStandalone);
759    XML_SetParamEntityParsing(parser, paramEntityParsing);
760    if (outputType == 't') {
761      /* This is for doing timings; this gives a more realistic estimate of
762         the parsing time. */
763      outputDir = 0;
764      XML_SetElementHandler(parser, nopStartElement, nopEndElement);
765      XML_SetCharacterDataHandler(parser, nopCharacterData);
766      XML_SetProcessingInstructionHandler(parser, nopProcessingInstruction);
767    }
768    else if (outputDir) {
769      const XML_Char *file = useStdin ? T("STDIN") : argv[i];
770      if (tcsrchr(file, T('/')))
771        file = tcsrchr(file, T('/')) + 1;
772#ifdef WIN32
773      if (tcsrchr(file, T('\\')))
774        file = tcsrchr(file, T('\\')) + 1;
775#endif
776      outName = malloc((tcslen(outputDir) + tcslen(file) + 2)
777                       * sizeof(XML_Char));
778      tcscpy(outName, outputDir);
779      tcscat(outName, T("/"));
780      tcscat(outName, file);
781      fp = tfopen(outName, T("wb"));
782      if (!fp) {
783        tperror(outName);
784        exit(1);
785      }
786      setvbuf(fp, NULL, _IOFBF, 16384);
787#ifdef XML_UNICODE
788      puttc(0xFEFF, fp);
789#endif
790      XML_SetUserData(parser, fp);
791      switch (outputType) {
792      case 'm':
793        XML_UseParserAsHandlerArg(parser);
794        XML_SetElementHandler(parser, metaStartElement, metaEndElement);
795        XML_SetProcessingInstructionHandler(parser, metaProcessingInstruction);
796        XML_SetCommentHandler(parser, metaComment);
797        XML_SetCdataSectionHandler(parser, metaStartCdataSection,
798                                   metaEndCdataSection);
799        XML_SetCharacterDataHandler(parser, metaCharacterData);
800        XML_SetDoctypeDeclHandler(parser, metaStartDoctypeDecl,
801                                  metaEndDoctypeDecl);
802        XML_SetEntityDeclHandler(parser, metaEntityDecl);
803        XML_SetNotationDeclHandler(parser, metaNotationDecl);
804        XML_SetNamespaceDeclHandler(parser, metaStartNamespaceDecl,
805                                    metaEndNamespaceDecl);
806        metaStartDocument(parser);
807        break;
808      case 'c':
809        XML_UseParserAsHandlerArg(parser);
810        XML_SetDefaultHandler(parser, markup);
811        XML_SetElementHandler(parser, defaultStartElement, defaultEndElement);
812        XML_SetCharacterDataHandler(parser, defaultCharacterData);
813        XML_SetProcessingInstructionHandler(parser,
814                                            defaultProcessingInstruction);
815        break;
816      default:
817        if (useNamespaces)
818          XML_SetElementHandler(parser, startElementNS, endElementNS);
819        else
820          XML_SetElementHandler(parser, startElement, endElement);
821        XML_SetCharacterDataHandler(parser, characterData);
822#ifndef W3C14N
823        XML_SetProcessingInstructionHandler(parser, processingInstruction);
824#endif /* not W3C14N */
825        break;
826      }
827    }
828    if (windowsCodePages)
829      XML_SetUnknownEncodingHandler(parser, unknownEncoding, 0);
830    result = XML_ProcessFile(parser, useStdin ? NULL : argv[i], processFlags);
831    if (outputDir) {
832      if (outputType == 'm')
833        metaEndDocument(parser);
834      fclose(fp);
835      if (!result)
836        tremove(outName);
837      free(outName);
838    }
839    XML_ParserFree(parser);
840  }
841  return 0;
842}
843