Coverage Report

Created: 2025-07-18 06:08

/src/tinysparql/subprojects/libxml2-2.13.1/debugXML.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * debugXML.c : This is a set of routines used for debugging the tree
3
 *              produced by the XML parser.
4
 *
5
 * See Copyright for the status of this software.
6
 *
7
 * Daniel Veillard <daniel@veillard.com>
8
 */
9
10
#define IN_LIBXML
11
#include "libxml.h"
12
#ifdef LIBXML_DEBUG_ENABLED
13
14
#include <string.h>
15
#include <stdlib.h>
16
17
#include <libxml/xmlmemory.h>
18
#include <libxml/tree.h>
19
#include <libxml/parser.h>
20
#include <libxml/parserInternals.h>
21
#include <libxml/debugXML.h>
22
#include <libxml/HTMLtree.h>
23
#include <libxml/HTMLparser.h>
24
#include <libxml/xmlerror.h>
25
#include <libxml/xpathInternals.h>
26
#include <libxml/uri.h>
27
#ifdef LIBXML_SCHEMAS_ENABLED
28
#include <libxml/relaxng.h>
29
#endif
30
31
#include "private/error.h"
32
33
0
#define DUMP_TEXT_TYPE 1
34
35
typedef struct _xmlDebugCtxt xmlDebugCtxt;
36
typedef xmlDebugCtxt *xmlDebugCtxtPtr;
37
struct _xmlDebugCtxt {
38
    FILE *output;               /* the output file */
39
    char shift[101];            /* used for indenting */
40
    int depth;                  /* current depth */
41
    xmlDocPtr doc;              /* current document */
42
    xmlNodePtr node;    /* current node */
43
    xmlDictPtr dict;    /* the doc dictionary */
44
    int check;                  /* do just checkings */
45
    int errors;                 /* number of errors found */
46
    int nodict;     /* if the document has no dictionary */
47
    int options;    /* options */
48
};
49
50
static void xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node);
51
52
static void
53
xmlCtxtDumpInitCtxt(xmlDebugCtxtPtr ctxt)
54
0
{
55
0
    int i;
56
57
0
    ctxt->depth = 0;
58
0
    ctxt->check = 0;
59
0
    ctxt->errors = 0;
60
0
    ctxt->output = stdout;
61
0
    ctxt->doc = NULL;
62
0
    ctxt->node = NULL;
63
0
    ctxt->dict = NULL;
64
0
    ctxt->nodict = 0;
65
0
    ctxt->options = 0;
66
0
    for (i = 0; i < 100; i++)
67
0
        ctxt->shift[i] = ' ';
68
0
    ctxt->shift[100] = 0;
69
0
}
70
71
static void
72
xmlCtxtDumpCleanCtxt(xmlDebugCtxtPtr ctxt ATTRIBUTE_UNUSED)
73
0
{
74
 /* remove the ATTRIBUTE_UNUSED when this is added */
75
0
}
76
77
/**
78
 * xmlNsCheckScope:
79
 * @node: the node
80
 * @ns: the namespace node
81
 *
82
 * Check that a given namespace is in scope on a node.
83
 *
84
 * Returns 1 if in scope, -1 in case of argument error,
85
 *         -2 if the namespace is not in scope, and -3 if not on
86
 *         an ancestor node.
87
 */
88
static int
89
xmlNsCheckScope(xmlNodePtr node, xmlNsPtr ns)
90
0
{
91
0
    xmlNsPtr cur;
92
93
0
    if ((node == NULL) || (ns == NULL))
94
0
        return(-1);
95
96
0
    if ((node->type != XML_ELEMENT_NODE) &&
97
0
  (node->type != XML_ATTRIBUTE_NODE) &&
98
0
  (node->type != XML_DOCUMENT_NODE) &&
99
0
  (node->type != XML_TEXT_NODE) &&
100
0
  (node->type != XML_HTML_DOCUMENT_NODE) &&
101
0
  (node->type != XML_XINCLUDE_START))
102
0
  return(-2);
103
104
0
    while ((node != NULL) &&
105
0
           ((node->type == XML_ELEMENT_NODE) ||
106
0
            (node->type == XML_ATTRIBUTE_NODE) ||
107
0
            (node->type == XML_TEXT_NODE) ||
108
0
      (node->type == XML_XINCLUDE_START))) {
109
0
  if ((node->type == XML_ELEMENT_NODE) ||
110
0
      (node->type == XML_XINCLUDE_START)) {
111
0
      cur = node->nsDef;
112
0
      while (cur != NULL) {
113
0
          if (cur == ns)
114
0
        return(1);
115
0
    if (xmlStrEqual(cur->prefix, ns->prefix))
116
0
        return(-2);
117
0
    cur = cur->next;
118
0
      }
119
0
  }
120
0
  node = node->parent;
121
0
    }
122
    /* the xml namespace may be declared on the document node */
123
0
    if ((node != NULL) &&
124
0
        ((node->type == XML_DOCUMENT_NODE) ||
125
0
   (node->type == XML_HTML_DOCUMENT_NODE))) {
126
0
   xmlNsPtr oldNs = ((xmlDocPtr) node)->oldNs;
127
0
   if (oldNs == ns)
128
0
       return(1);
129
0
    }
130
0
    return(-3);
131
0
}
132
133
static void
134
xmlCtxtDumpSpaces(xmlDebugCtxtPtr ctxt)
135
0
{
136
0
    if (ctxt->check)
137
0
        return;
138
0
    if ((ctxt->output != NULL) && (ctxt->depth > 0)) {
139
0
        if (ctxt->depth < 50)
140
0
            fprintf(ctxt->output, "%s", &ctxt->shift[100 - 2 * ctxt->depth]);
141
0
        else
142
0
            fprintf(ctxt->output, "%s", ctxt->shift);
143
0
    }
144
0
}
145
146
/**
147
 * xmlDebugErr:
148
 * @ctxt:  a debug context
149
 * @error:  the error code
150
 *
151
 * Handle a debug error.
152
 */
153
static void
154
xmlDebugErr(xmlDebugCtxtPtr ctxt, int error, const char *msg)
155
0
{
156
0
    ctxt->errors++;
157
0
    fprintf(ctxt->output, "ERROR %d: %s", error, msg);
158
0
}
159
static void LIBXML_ATTR_FORMAT(3,0)
160
xmlDebugErr2(xmlDebugCtxtPtr ctxt, int error, const char *msg, int extra)
161
0
{
162
0
    ctxt->errors++;
163
0
    fprintf(ctxt->output, "ERROR %d: ", error);
164
0
    fprintf(ctxt->output, msg, extra);
165
0
}
166
static void LIBXML_ATTR_FORMAT(3,0)
167
xmlDebugErr3(xmlDebugCtxtPtr ctxt, int error, const char *msg, const char *extra)
168
0
{
169
0
    ctxt->errors++;
170
0
    fprintf(ctxt->output, "ERROR %d: ", error);
171
0
    fprintf(ctxt->output, msg, extra);
172
0
}
173
174
/**
175
 * xmlCtxtNsCheckScope:
176
 * @ctxt: the debugging context
177
 * @node: the node
178
 * @ns: the namespace node
179
 *
180
 * Report if a given namespace is is not in scope.
181
 */
182
static void
183
xmlCtxtNsCheckScope(xmlDebugCtxtPtr ctxt, xmlNodePtr node, xmlNsPtr ns)
184
0
{
185
0
    int ret;
186
187
0
    ret = xmlNsCheckScope(node, ns);
188
0
    if (ret == -2) {
189
0
        if (ns->prefix == NULL)
190
0
      xmlDebugErr(ctxt, XML_CHECK_NS_SCOPE,
191
0
      "Reference to default namespace not in scope\n");
192
0
  else
193
0
      xmlDebugErr3(ctxt, XML_CHECK_NS_SCOPE,
194
0
       "Reference to namespace '%s' not in scope\n",
195
0
       (char *) ns->prefix);
196
0
    }
197
0
    if (ret == -3) {
198
0
        if (ns->prefix == NULL)
199
0
      xmlDebugErr(ctxt, XML_CHECK_NS_ANCESTOR,
200
0
      "Reference to default namespace not on ancestor\n");
201
0
  else
202
0
      xmlDebugErr3(ctxt, XML_CHECK_NS_ANCESTOR,
203
0
       "Reference to namespace '%s' not on ancestor\n",
204
0
       (char *) ns->prefix);
205
0
    }
206
0
}
207
208
/**
209
 * xmlCtxtCheckString:
210
 * @ctxt: the debug context
211
 * @str: the string
212
 *
213
 * Do debugging on the string, currently it just checks the UTF-8 content
214
 */
215
static void
216
xmlCtxtCheckString(xmlDebugCtxtPtr ctxt, const xmlChar * str)
217
0
{
218
0
    if (str == NULL) return;
219
0
    if (ctxt->check) {
220
0
        if (!xmlCheckUTF8(str)) {
221
0
      xmlDebugErr3(ctxt, XML_CHECK_NOT_UTF8,
222
0
       "String is not UTF-8 %s", (const char *) str);
223
0
  }
224
0
    }
225
0
}
226
227
/**
228
 * xmlCtxtCheckName:
229
 * @ctxt: the debug context
230
 * @name: the name
231
 *
232
 * Do debugging on the name, for example the dictionary status and
233
 * conformance to the Name production.
234
 */
235
static void
236
xmlCtxtCheckName(xmlDebugCtxtPtr ctxt, const xmlChar * name)
237
0
{
238
0
    if (ctxt->check) {
239
0
  if (name == NULL) {
240
0
      xmlDebugErr(ctxt, XML_CHECK_NO_NAME, "Name is NULL");
241
0
      return;
242
0
  }
243
0
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
244
0
        if (xmlValidateName(name, 0)) {
245
0
      xmlDebugErr3(ctxt, XML_CHECK_NOT_NCNAME,
246
0
       "Name is not an NCName '%s'", (const char *) name);
247
0
  }
248
0
#endif
249
0
  if ((ctxt->dict != NULL) &&
250
0
      (!xmlDictOwns(ctxt->dict, name)) &&
251
0
            ((ctxt->doc == NULL) ||
252
0
             ((ctxt->doc->parseFlags & (XML_PARSE_SAX1 | XML_PARSE_NODICT)) == 0))) {
253
0
      xmlDebugErr3(ctxt, XML_CHECK_OUTSIDE_DICT,
254
0
       "Name is not from the document dictionary '%s'",
255
0
       (const char *) name);
256
0
  }
257
0
    }
258
0
}
259
260
static void
261
0
xmlCtxtGenericNodeCheck(xmlDebugCtxtPtr ctxt, xmlNodePtr node) {
262
0
    xmlDocPtr doc;
263
0
    xmlDictPtr dict;
264
265
0
    doc = node->doc;
266
267
0
    if (node->parent == NULL)
268
0
        xmlDebugErr(ctxt, XML_CHECK_NO_PARENT,
269
0
              "Node has no parent\n");
270
0
    if (node->doc == NULL) {
271
0
        xmlDebugErr(ctxt, XML_CHECK_NO_DOC,
272
0
              "Node has no doc\n");
273
0
        dict = NULL;
274
0
    } else {
275
0
  dict = doc->dict;
276
0
  if ((dict == NULL) && (ctxt->nodict == 0)) {
277
#if 0
278
            /* deactivated right now as it raises too many errors */
279
      if (doc->type == XML_DOCUMENT_NODE)
280
    xmlDebugErr(ctxt, XML_CHECK_NO_DICT,
281
          "Document has no dictionary\n");
282
#endif
283
0
      ctxt->nodict = 1;
284
0
  }
285
0
  if (ctxt->doc == NULL)
286
0
      ctxt->doc = doc;
287
288
0
  if (ctxt->dict == NULL) {
289
0
      ctxt->dict = dict;
290
0
  }
291
0
    }
292
0
    if ((node->parent != NULL) && (node->doc != node->parent->doc) &&
293
0
        (!xmlStrEqual(node->name, BAD_CAST "pseudoroot")))
294
0
        xmlDebugErr(ctxt, XML_CHECK_WRONG_DOC,
295
0
              "Node doc differs from parent's one\n");
296
0
    if (node->prev == NULL) {
297
0
        if (node->type == XML_ATTRIBUTE_NODE) {
298
0
      if ((node->parent != NULL) &&
299
0
          (node != (xmlNodePtr) node->parent->properties))
300
0
    xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
301
0
                    "Attr has no prev and not first of attr list\n");
302
303
0
        } else if ((node->parent != NULL) && (node->parent->children != node))
304
0
      xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
305
0
                    "Node has no prev and not first of parent list\n");
306
0
    } else {
307
0
        if (node->prev->next != node)
308
0
      xmlDebugErr(ctxt, XML_CHECK_WRONG_PREV,
309
0
                        "Node prev->next : back link wrong\n");
310
0
    }
311
0
    if (node->next == NULL) {
312
0
  if ((node->parent != NULL) && (node->type != XML_ATTRIBUTE_NODE) &&
313
0
      (node->parent->last != node) &&
314
0
      (node->parent->type == XML_ELEMENT_NODE))
315
0
      xmlDebugErr(ctxt, XML_CHECK_NO_NEXT,
316
0
                    "Node has no next and not last of parent list\n");
317
0
    } else {
318
0
        if (node->next->prev != node)
319
0
      xmlDebugErr(ctxt, XML_CHECK_WRONG_NEXT,
320
0
                    "Node next->prev : forward link wrong\n");
321
0
        if (node->next->parent != node->parent)
322
0
      xmlDebugErr(ctxt, XML_CHECK_WRONG_PARENT,
323
0
                    "Node next->prev : forward link wrong\n");
324
0
    }
325
0
    if (node->type == XML_ELEMENT_NODE) {
326
0
        xmlNsPtr ns;
327
328
0
  ns = node->nsDef;
329
0
  while (ns != NULL) {
330
0
      xmlCtxtNsCheckScope(ctxt, node, ns);
331
0
      ns = ns->next;
332
0
  }
333
0
  if (node->ns != NULL)
334
0
      xmlCtxtNsCheckScope(ctxt, node, node->ns);
335
0
    } else if (node->type == XML_ATTRIBUTE_NODE) {
336
0
  if (node->ns != NULL)
337
0
      xmlCtxtNsCheckScope(ctxt, node, node->ns);
338
0
    }
339
340
0
    if ((node->type != XML_ELEMENT_NODE) &&
341
0
  (node->type != XML_ATTRIBUTE_NODE) &&
342
0
  (node->type != XML_ELEMENT_DECL) &&
343
0
  (node->type != XML_ATTRIBUTE_DECL) &&
344
0
  (node->type != XML_DTD_NODE) &&
345
0
  (node->type != XML_HTML_DOCUMENT_NODE) &&
346
0
  (node->type != XML_DOCUMENT_NODE)) {
347
0
  if (node->content != NULL)
348
0
      xmlCtxtCheckString(ctxt, (const xmlChar *) node->content);
349
0
    }
350
0
    switch (node->type) {
351
0
        case XML_ELEMENT_NODE:
352
0
        case XML_ATTRIBUTE_NODE:
353
0
      xmlCtxtCheckName(ctxt, node->name);
354
0
      break;
355
0
        case XML_TEXT_NODE:
356
0
      if ((node->name == xmlStringText) ||
357
0
          (node->name == xmlStringTextNoenc))
358
0
    break;
359
      /* some case of entity substitution can lead to this */
360
0
      if ((ctxt->dict != NULL) &&
361
0
          (node->name == xmlDictLookup(ctxt->dict, BAD_CAST "nbktext",
362
0
                                 7)))
363
0
    break;
364
365
0
      xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME,
366
0
       "Text node has wrong name '%s'",
367
0
       (const char *) node->name);
368
0
      break;
369
0
        case XML_COMMENT_NODE:
370
0
      if (node->name == xmlStringComment)
371
0
    break;
372
0
      xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME,
373
0
       "Comment node has wrong name '%s'",
374
0
       (const char *) node->name);
375
0
      break;
376
0
        case XML_PI_NODE:
377
0
      xmlCtxtCheckName(ctxt, node->name);
378
0
      break;
379
0
        case XML_CDATA_SECTION_NODE:
380
0
      if (node->name == NULL)
381
0
    break;
382
0
      xmlDebugErr3(ctxt, XML_CHECK_NAME_NOT_NULL,
383
0
       "CData section has non NULL name '%s'",
384
0
       (const char *) node->name);
385
0
      break;
386
0
        case XML_ENTITY_REF_NODE:
387
0
        case XML_ENTITY_NODE:
388
0
        case XML_DOCUMENT_TYPE_NODE:
389
0
        case XML_DOCUMENT_FRAG_NODE:
390
0
        case XML_NOTATION_NODE:
391
0
        case XML_DTD_NODE:
392
0
        case XML_ELEMENT_DECL:
393
0
        case XML_ATTRIBUTE_DECL:
394
0
        case XML_ENTITY_DECL:
395
0
        case XML_NAMESPACE_DECL:
396
0
        case XML_XINCLUDE_START:
397
0
        case XML_XINCLUDE_END:
398
0
        case XML_DOCUMENT_NODE:
399
0
        case XML_HTML_DOCUMENT_NODE:
400
0
      break;
401
0
    }
402
0
}
403
404
static void
405
xmlCtxtDumpString(xmlDebugCtxtPtr ctxt, const xmlChar * str)
406
0
{
407
0
    int i;
408
409
0
    if (ctxt->check) {
410
0
        return;
411
0
    }
412
    /* TODO: check UTF8 content of the string */
413
0
    if (str == NULL) {
414
0
        fprintf(ctxt->output, "(NULL)");
415
0
        return;
416
0
    }
417
0
    for (i = 0; i < 40; i++)
418
0
        if (str[i] == 0)
419
0
            return;
420
0
        else if (IS_BLANK_CH(str[i]))
421
0
            fputc(' ', ctxt->output);
422
0
        else if (str[i] >= 0x80)
423
0
            fprintf(ctxt->output, "#%X", str[i]);
424
0
        else
425
0
            fputc(str[i], ctxt->output);
426
0
    fprintf(ctxt->output, "...");
427
0
}
428
429
static void
430
xmlCtxtDumpDtdNode(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd)
431
0
{
432
0
    xmlCtxtDumpSpaces(ctxt);
433
434
0
    if (dtd == NULL) {
435
0
        if (!ctxt->check)
436
0
            fprintf(ctxt->output, "DTD node is NULL\n");
437
0
        return;
438
0
    }
439
440
0
    if (dtd->type != XML_DTD_NODE) {
441
0
  xmlDebugErr(ctxt, XML_CHECK_NOT_DTD,
442
0
              "Node is not a DTD");
443
0
        return;
444
0
    }
445
0
    if (!ctxt->check) {
446
0
        if (dtd->name != NULL)
447
0
            fprintf(ctxt->output, "DTD(%s)", (char *) dtd->name);
448
0
        else
449
0
            fprintf(ctxt->output, "DTD");
450
0
        if (dtd->ExternalID != NULL)
451
0
            fprintf(ctxt->output, ", PUBLIC %s", (char *) dtd->ExternalID);
452
0
        if (dtd->SystemID != NULL)
453
0
            fprintf(ctxt->output, ", SYSTEM %s", (char *) dtd->SystemID);
454
0
        fprintf(ctxt->output, "\n");
455
0
    }
456
    /*
457
     * Do a bit of checking
458
     */
459
0
    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) dtd);
460
0
}
461
462
static void
463
xmlCtxtDumpAttrDecl(xmlDebugCtxtPtr ctxt, xmlAttributePtr attr)
464
0
{
465
0
    xmlCtxtDumpSpaces(ctxt);
466
467
0
    if (attr == NULL) {
468
0
        if (!ctxt->check)
469
0
            fprintf(ctxt->output, "Attribute declaration is NULL\n");
470
0
        return;
471
0
    }
472
0
    if (attr->type != XML_ATTRIBUTE_DECL) {
473
0
  xmlDebugErr(ctxt, XML_CHECK_NOT_ATTR_DECL,
474
0
              "Node is not an attribute declaration");
475
0
        return;
476
0
    }
477
0
    if (attr->name != NULL) {
478
0
        if (!ctxt->check)
479
0
            fprintf(ctxt->output, "ATTRDECL(%s)", (char *) attr->name);
480
0
    } else
481
0
  xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
482
0
              "Node attribute declaration has no name");
483
0
    if (attr->elem != NULL) {
484
0
        if (!ctxt->check)
485
0
            fprintf(ctxt->output, " for %s", (char *) attr->elem);
486
0
    } else
487
0
  xmlDebugErr(ctxt, XML_CHECK_NO_ELEM,
488
0
              "Node attribute declaration has no element name");
489
0
    if (!ctxt->check) {
490
0
        switch (attr->atype) {
491
0
            case XML_ATTRIBUTE_CDATA:
492
0
                fprintf(ctxt->output, " CDATA");
493
0
                break;
494
0
            case XML_ATTRIBUTE_ID:
495
0
                fprintf(ctxt->output, " ID");
496
0
                break;
497
0
            case XML_ATTRIBUTE_IDREF:
498
0
                fprintf(ctxt->output, " IDREF");
499
0
                break;
500
0
            case XML_ATTRIBUTE_IDREFS:
501
0
                fprintf(ctxt->output, " IDREFS");
502
0
                break;
503
0
            case XML_ATTRIBUTE_ENTITY:
504
0
                fprintf(ctxt->output, " ENTITY");
505
0
                break;
506
0
            case XML_ATTRIBUTE_ENTITIES:
507
0
                fprintf(ctxt->output, " ENTITIES");
508
0
                break;
509
0
            case XML_ATTRIBUTE_NMTOKEN:
510
0
                fprintf(ctxt->output, " NMTOKEN");
511
0
                break;
512
0
            case XML_ATTRIBUTE_NMTOKENS:
513
0
                fprintf(ctxt->output, " NMTOKENS");
514
0
                break;
515
0
            case XML_ATTRIBUTE_ENUMERATION:
516
0
                fprintf(ctxt->output, " ENUMERATION");
517
0
                break;
518
0
            case XML_ATTRIBUTE_NOTATION:
519
0
                fprintf(ctxt->output, " NOTATION ");
520
0
                break;
521
0
        }
522
0
        if (attr->tree != NULL) {
523
0
            int indx;
524
0
            xmlEnumerationPtr cur = attr->tree;
525
526
0
            for (indx = 0; indx < 5; indx++) {
527
0
                if (indx != 0)
528
0
                    fprintf(ctxt->output, "|%s", (char *) cur->name);
529
0
                else
530
0
                    fprintf(ctxt->output, " (%s", (char *) cur->name);
531
0
                cur = cur->next;
532
0
                if (cur == NULL)
533
0
                    break;
534
0
            }
535
0
            if (cur == NULL)
536
0
                fprintf(ctxt->output, ")");
537
0
            else
538
0
                fprintf(ctxt->output, "...)");
539
0
        }
540
0
        switch (attr->def) {
541
0
            case XML_ATTRIBUTE_NONE:
542
0
                break;
543
0
            case XML_ATTRIBUTE_REQUIRED:
544
0
                fprintf(ctxt->output, " REQUIRED");
545
0
                break;
546
0
            case XML_ATTRIBUTE_IMPLIED:
547
0
                fprintf(ctxt->output, " IMPLIED");
548
0
                break;
549
0
            case XML_ATTRIBUTE_FIXED:
550
0
                fprintf(ctxt->output, " FIXED");
551
0
                break;
552
0
        }
553
0
        if (attr->defaultValue != NULL) {
554
0
            fprintf(ctxt->output, "\"");
555
0
            xmlCtxtDumpString(ctxt, attr->defaultValue);
556
0
            fprintf(ctxt->output, "\"");
557
0
        }
558
0
        fprintf(ctxt->output, "\n");
559
0
    }
560
561
    /*
562
     * Do a bit of checking
563
     */
564
0
    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr);
565
0
}
566
567
static void
568
xmlCtxtDumpElemDecl(xmlDebugCtxtPtr ctxt, xmlElementPtr elem)
569
0
{
570
0
    xmlCtxtDumpSpaces(ctxt);
571
572
0
    if (elem == NULL) {
573
0
        if (!ctxt->check)
574
0
            fprintf(ctxt->output, "Element declaration is NULL\n");
575
0
        return;
576
0
    }
577
0
    if (elem->type != XML_ELEMENT_DECL) {
578
0
  xmlDebugErr(ctxt, XML_CHECK_NOT_ELEM_DECL,
579
0
              "Node is not an element declaration");
580
0
        return;
581
0
    }
582
0
    if (elem->name != NULL) {
583
0
        if (!ctxt->check) {
584
0
            fprintf(ctxt->output, "ELEMDECL(");
585
0
            xmlCtxtDumpString(ctxt, elem->name);
586
0
            fprintf(ctxt->output, ")");
587
0
        }
588
0
    } else
589
0
  xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
590
0
              "Element declaration has no name");
591
0
    if (!ctxt->check) {
592
0
        switch (elem->etype) {
593
0
            case XML_ELEMENT_TYPE_UNDEFINED:
594
0
                fprintf(ctxt->output, ", UNDEFINED");
595
0
                break;
596
0
            case XML_ELEMENT_TYPE_EMPTY:
597
0
                fprintf(ctxt->output, ", EMPTY");
598
0
                break;
599
0
            case XML_ELEMENT_TYPE_ANY:
600
0
                fprintf(ctxt->output, ", ANY");
601
0
                break;
602
0
            case XML_ELEMENT_TYPE_MIXED:
603
0
                fprintf(ctxt->output, ", MIXED ");
604
0
                break;
605
0
            case XML_ELEMENT_TYPE_ELEMENT:
606
0
                fprintf(ctxt->output, ", MIXED ");
607
0
                break;
608
0
        }
609
0
        if ((elem->type != XML_ELEMENT_NODE) && (elem->content != NULL)) {
610
0
            char buf[5001];
611
612
0
            buf[0] = 0;
613
0
            xmlSnprintfElementContent(buf, 5000, elem->content, 1);
614
0
            buf[5000] = 0;
615
0
            fprintf(ctxt->output, "%s", buf);
616
0
        }
617
0
        fprintf(ctxt->output, "\n");
618
0
    }
619
620
    /*
621
     * Do a bit of checking
622
     */
623
0
    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) elem);
624
0
}
625
626
static void
627
xmlCtxtDumpEntityDecl(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent)
628
0
{
629
0
    xmlCtxtDumpSpaces(ctxt);
630
631
0
    if (ent == NULL) {
632
0
        if (!ctxt->check)
633
0
            fprintf(ctxt->output, "Entity declaration is NULL\n");
634
0
        return;
635
0
    }
636
0
    if (ent->type != XML_ENTITY_DECL) {
637
0
  xmlDebugErr(ctxt, XML_CHECK_NOT_ENTITY_DECL,
638
0
              "Node is not an entity declaration");
639
0
        return;
640
0
    }
641
0
    if (ent->name != NULL) {
642
0
        if (!ctxt->check) {
643
0
            fprintf(ctxt->output, "ENTITYDECL(");
644
0
            xmlCtxtDumpString(ctxt, ent->name);
645
0
            fprintf(ctxt->output, ")");
646
0
        }
647
0
    } else
648
0
  xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
649
0
              "Entity declaration has no name");
650
0
    if (!ctxt->check) {
651
0
        switch (ent->etype) {
652
0
            case XML_INTERNAL_GENERAL_ENTITY:
653
0
                fprintf(ctxt->output, ", internal\n");
654
0
                break;
655
0
            case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
656
0
                fprintf(ctxt->output, ", external parsed\n");
657
0
                break;
658
0
            case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
659
0
                fprintf(ctxt->output, ", unparsed\n");
660
0
                break;
661
0
            case XML_INTERNAL_PARAMETER_ENTITY:
662
0
                fprintf(ctxt->output, ", parameter\n");
663
0
                break;
664
0
            case XML_EXTERNAL_PARAMETER_ENTITY:
665
0
                fprintf(ctxt->output, ", external parameter\n");
666
0
                break;
667
0
            case XML_INTERNAL_PREDEFINED_ENTITY:
668
0
                fprintf(ctxt->output, ", predefined\n");
669
0
                break;
670
0
        }
671
0
        if (ent->ExternalID) {
672
0
            xmlCtxtDumpSpaces(ctxt);
673
0
            fprintf(ctxt->output, " ExternalID=%s\n",
674
0
                    (char *) ent->ExternalID);
675
0
        }
676
0
        if (ent->SystemID) {
677
0
            xmlCtxtDumpSpaces(ctxt);
678
0
            fprintf(ctxt->output, " SystemID=%s\n",
679
0
                    (char *) ent->SystemID);
680
0
        }
681
0
        if (ent->URI != NULL) {
682
0
            xmlCtxtDumpSpaces(ctxt);
683
0
            fprintf(ctxt->output, " URI=%s\n", (char *) ent->URI);
684
0
        }
685
0
        if (ent->content) {
686
0
            xmlCtxtDumpSpaces(ctxt);
687
0
            fprintf(ctxt->output, " content=");
688
0
            xmlCtxtDumpString(ctxt, ent->content);
689
0
            fprintf(ctxt->output, "\n");
690
0
        }
691
0
    }
692
693
    /*
694
     * Do a bit of checking
695
     */
696
0
    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) ent);
697
0
}
698
699
static void
700
xmlCtxtDumpNamespace(xmlDebugCtxtPtr ctxt, xmlNsPtr ns)
701
0
{
702
0
    xmlCtxtDumpSpaces(ctxt);
703
704
0
    if (ns == NULL) {
705
0
        if (!ctxt->check)
706
0
            fprintf(ctxt->output, "namespace node is NULL\n");
707
0
        return;
708
0
    }
709
0
    if (ns->type != XML_NAMESPACE_DECL) {
710
0
  xmlDebugErr(ctxt, XML_CHECK_NOT_NS_DECL,
711
0
              "Node is not a namespace declaration");
712
0
        return;
713
0
    }
714
0
    if (ns->href == NULL) {
715
0
        if (ns->prefix != NULL)
716
0
      xmlDebugErr3(ctxt, XML_CHECK_NO_HREF,
717
0
                    "Incomplete namespace %s href=NULL\n",
718
0
                    (char *) ns->prefix);
719
0
        else
720
0
      xmlDebugErr(ctxt, XML_CHECK_NO_HREF,
721
0
                    "Incomplete default namespace href=NULL\n");
722
0
    } else {
723
0
        if (!ctxt->check) {
724
0
            if (ns->prefix != NULL)
725
0
                fprintf(ctxt->output, "namespace %s href=",
726
0
                        (char *) ns->prefix);
727
0
            else
728
0
                fprintf(ctxt->output, "default namespace href=");
729
730
0
            xmlCtxtDumpString(ctxt, ns->href);
731
0
            fprintf(ctxt->output, "\n");
732
0
        }
733
0
    }
734
0
}
735
736
static void
737
xmlCtxtDumpNamespaceList(xmlDebugCtxtPtr ctxt, xmlNsPtr ns)
738
0
{
739
0
    while (ns != NULL) {
740
0
        xmlCtxtDumpNamespace(ctxt, ns);
741
0
        ns = ns->next;
742
0
    }
743
0
}
744
745
static void
746
xmlCtxtDumpEntity(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent)
747
0
{
748
0
    xmlCtxtDumpSpaces(ctxt);
749
750
0
    if (ent == NULL) {
751
0
        if (!ctxt->check)
752
0
            fprintf(ctxt->output, "Entity is NULL\n");
753
0
        return;
754
0
    }
755
0
    if (!ctxt->check) {
756
0
        switch (ent->etype) {
757
0
            case XML_INTERNAL_GENERAL_ENTITY:
758
0
                fprintf(ctxt->output, "INTERNAL_GENERAL_ENTITY ");
759
0
                break;
760
0
            case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
761
0
                fprintf(ctxt->output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
762
0
                break;
763
0
            case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
764
0
                fprintf(ctxt->output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
765
0
                break;
766
0
            case XML_INTERNAL_PARAMETER_ENTITY:
767
0
                fprintf(ctxt->output, "INTERNAL_PARAMETER_ENTITY ");
768
0
                break;
769
0
            case XML_EXTERNAL_PARAMETER_ENTITY:
770
0
                fprintf(ctxt->output, "EXTERNAL_PARAMETER_ENTITY ");
771
0
                break;
772
0
            default:
773
0
                fprintf(ctxt->output, "ENTITY_%d ! ", (int) ent->etype);
774
0
        }
775
0
        fprintf(ctxt->output, "%s\n", ent->name);
776
0
        if (ent->ExternalID) {
777
0
            xmlCtxtDumpSpaces(ctxt);
778
0
            fprintf(ctxt->output, "ExternalID=%s\n",
779
0
                    (char *) ent->ExternalID);
780
0
        }
781
0
        if (ent->SystemID) {
782
0
            xmlCtxtDumpSpaces(ctxt);
783
0
            fprintf(ctxt->output, "SystemID=%s\n", (char *) ent->SystemID);
784
0
        }
785
0
        if (ent->URI) {
786
0
            xmlCtxtDumpSpaces(ctxt);
787
0
            fprintf(ctxt->output, "URI=%s\n", (char *) ent->URI);
788
0
        }
789
0
        if (ent->content) {
790
0
            xmlCtxtDumpSpaces(ctxt);
791
0
            fprintf(ctxt->output, "content=");
792
0
            xmlCtxtDumpString(ctxt, ent->content);
793
0
            fprintf(ctxt->output, "\n");
794
0
        }
795
0
    }
796
0
}
797
798
/**
799
 * xmlCtxtDumpAttr:
800
 * @output:  the FILE * for the output
801
 * @attr:  the attribute
802
 * @depth:  the indentation level.
803
 *
804
 * Dumps debug information for the attribute
805
 */
806
static void
807
xmlCtxtDumpAttr(xmlDebugCtxtPtr ctxt, xmlAttrPtr attr)
808
0
{
809
0
    xmlCtxtDumpSpaces(ctxt);
810
811
0
    if (attr == NULL) {
812
0
        if (!ctxt->check)
813
0
            fprintf(ctxt->output, "Attr is NULL");
814
0
        return;
815
0
    }
816
0
    if (!ctxt->check) {
817
0
        fprintf(ctxt->output, "ATTRIBUTE ");
818
0
  xmlCtxtDumpString(ctxt, attr->name);
819
0
        fprintf(ctxt->output, "\n");
820
0
        if (attr->children != NULL) {
821
0
            ctxt->depth++;
822
0
            xmlCtxtDumpNodeList(ctxt, attr->children);
823
0
            ctxt->depth--;
824
0
        }
825
0
    }
826
0
    if (attr->name == NULL)
827
0
  xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
828
0
              "Attribute has no name");
829
830
    /*
831
     * Do a bit of checking
832
     */
833
0
    xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr);
834
0
}
835
836
/**
837
 * xmlCtxtDumpAttrList:
838
 * @output:  the FILE * for the output
839
 * @attr:  the attribute list
840
 * @depth:  the indentation level.
841
 *
842
 * Dumps debug information for the attribute list
843
 */
844
static void
845
xmlCtxtDumpAttrList(xmlDebugCtxtPtr ctxt, xmlAttrPtr attr)
846
0
{
847
0
    while (attr != NULL) {
848
0
        xmlCtxtDumpAttr(ctxt, attr);
849
0
        attr = attr->next;
850
0
    }
851
0
}
852
853
/**
854
 * xmlCtxtDumpOneNode:
855
 * @output:  the FILE * for the output
856
 * @node:  the node
857
 * @depth:  the indentation level.
858
 *
859
 * Dumps debug information for the element node, it is not recursive
860
 */
861
static void
862
xmlCtxtDumpOneNode(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
863
0
{
864
0
    if (node == NULL) {
865
0
        if (!ctxt->check) {
866
0
            xmlCtxtDumpSpaces(ctxt);
867
0
            fprintf(ctxt->output, "node is NULL\n");
868
0
        }
869
0
        return;
870
0
    }
871
0
    ctxt->node = node;
872
873
0
    switch (node->type) {
874
0
        case XML_ELEMENT_NODE:
875
0
            if (!ctxt->check) {
876
0
                xmlCtxtDumpSpaces(ctxt);
877
0
                fprintf(ctxt->output, "ELEMENT ");
878
0
                if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
879
0
                    xmlCtxtDumpString(ctxt, node->ns->prefix);
880
0
                    fprintf(ctxt->output, ":");
881
0
                }
882
0
                xmlCtxtDumpString(ctxt, node->name);
883
0
                fprintf(ctxt->output, "\n");
884
0
            }
885
0
            break;
886
0
        case XML_ATTRIBUTE_NODE:
887
0
            if (!ctxt->check)
888
0
                xmlCtxtDumpSpaces(ctxt);
889
0
            fprintf(ctxt->output, "Error, ATTRIBUTE found here\n");
890
0
            xmlCtxtGenericNodeCheck(ctxt, node);
891
0
            return;
892
0
        case XML_TEXT_NODE:
893
0
            if (!ctxt->check) {
894
0
                xmlCtxtDumpSpaces(ctxt);
895
0
                if (node->name == (const xmlChar *) xmlStringTextNoenc)
896
0
                    fprintf(ctxt->output, "TEXT no enc");
897
0
                else
898
0
                    fprintf(ctxt->output, "TEXT");
899
0
    if (ctxt->options & DUMP_TEXT_TYPE) {
900
0
        if (node->content == (xmlChar *) &(node->properties))
901
0
      fprintf(ctxt->output, " compact\n");
902
0
        else if (xmlDictOwns(ctxt->dict, node->content) == 1)
903
0
      fprintf(ctxt->output, " interned\n");
904
0
        else
905
0
      fprintf(ctxt->output, "\n");
906
0
    } else
907
0
        fprintf(ctxt->output, "\n");
908
0
            }
909
0
            break;
910
0
        case XML_CDATA_SECTION_NODE:
911
0
            if (!ctxt->check) {
912
0
                xmlCtxtDumpSpaces(ctxt);
913
0
                fprintf(ctxt->output, "CDATA_SECTION\n");
914
0
            }
915
0
            break;
916
0
        case XML_ENTITY_REF_NODE:
917
0
            if (!ctxt->check) {
918
0
                xmlCtxtDumpSpaces(ctxt);
919
0
                fprintf(ctxt->output, "ENTITY_REF(%s)\n",
920
0
                        (char *) node->name);
921
0
            }
922
0
            break;
923
0
        case XML_ENTITY_NODE:
924
0
            if (!ctxt->check) {
925
0
                xmlCtxtDumpSpaces(ctxt);
926
0
                fprintf(ctxt->output, "ENTITY\n");
927
0
            }
928
0
            break;
929
0
        case XML_PI_NODE:
930
0
            if (!ctxt->check) {
931
0
                xmlCtxtDumpSpaces(ctxt);
932
0
                fprintf(ctxt->output, "PI %s\n", (char *) node->name);
933
0
            }
934
0
            break;
935
0
        case XML_COMMENT_NODE:
936
0
            if (!ctxt->check) {
937
0
                xmlCtxtDumpSpaces(ctxt);
938
0
                fprintf(ctxt->output, "COMMENT\n");
939
0
            }
940
0
            break;
941
0
        case XML_DOCUMENT_NODE:
942
0
        case XML_HTML_DOCUMENT_NODE:
943
0
            if (!ctxt->check) {
944
0
                xmlCtxtDumpSpaces(ctxt);
945
0
            }
946
0
            fprintf(ctxt->output, "Error, DOCUMENT found here\n");
947
0
            xmlCtxtGenericNodeCheck(ctxt, node);
948
0
            return;
949
0
        case XML_DOCUMENT_TYPE_NODE:
950
0
            if (!ctxt->check) {
951
0
                xmlCtxtDumpSpaces(ctxt);
952
0
                fprintf(ctxt->output, "DOCUMENT_TYPE\n");
953
0
            }
954
0
            break;
955
0
        case XML_DOCUMENT_FRAG_NODE:
956
0
            if (!ctxt->check) {
957
0
                xmlCtxtDumpSpaces(ctxt);
958
0
                fprintf(ctxt->output, "DOCUMENT_FRAG\n");
959
0
            }
960
0
            break;
961
0
        case XML_NOTATION_NODE:
962
0
            if (!ctxt->check) {
963
0
                xmlCtxtDumpSpaces(ctxt);
964
0
                fprintf(ctxt->output, "NOTATION\n");
965
0
            }
966
0
            break;
967
0
        case XML_DTD_NODE:
968
0
            xmlCtxtDumpDtdNode(ctxt, (xmlDtdPtr) node);
969
0
            return;
970
0
        case XML_ELEMENT_DECL:
971
0
            xmlCtxtDumpElemDecl(ctxt, (xmlElementPtr) node);
972
0
            return;
973
0
        case XML_ATTRIBUTE_DECL:
974
0
            xmlCtxtDumpAttrDecl(ctxt, (xmlAttributePtr) node);
975
0
            return;
976
0
        case XML_ENTITY_DECL:
977
0
            xmlCtxtDumpEntityDecl(ctxt, (xmlEntityPtr) node);
978
0
            return;
979
0
        case XML_NAMESPACE_DECL:
980
0
            xmlCtxtDumpNamespace(ctxt, (xmlNsPtr) node);
981
0
            return;
982
0
        case XML_XINCLUDE_START:
983
0
            if (!ctxt->check) {
984
0
                xmlCtxtDumpSpaces(ctxt);
985
0
                fprintf(ctxt->output, "INCLUDE START\n");
986
0
            }
987
0
            return;
988
0
        case XML_XINCLUDE_END:
989
0
            if (!ctxt->check) {
990
0
                xmlCtxtDumpSpaces(ctxt);
991
0
                fprintf(ctxt->output, "INCLUDE END\n");
992
0
            }
993
0
            return;
994
0
        default:
995
0
            if (!ctxt->check)
996
0
                xmlCtxtDumpSpaces(ctxt);
997
0
      xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE,
998
0
                  "Unknown node type %d\n", node->type);
999
0
            return;
1000
0
    }
1001
0
    if (node->doc == NULL) {
1002
0
        if (!ctxt->check) {
1003
0
            xmlCtxtDumpSpaces(ctxt);
1004
0
        }
1005
0
        fprintf(ctxt->output, "PBM: doc == NULL !!!\n");
1006
0
    }
1007
0
    ctxt->depth++;
1008
0
    if ((node->type == XML_ELEMENT_NODE) && (node->nsDef != NULL))
1009
0
        xmlCtxtDumpNamespaceList(ctxt, node->nsDef);
1010
0
    if ((node->type == XML_ELEMENT_NODE) && (node->properties != NULL))
1011
0
        xmlCtxtDumpAttrList(ctxt, node->properties);
1012
0
    if (node->type != XML_ENTITY_REF_NODE) {
1013
0
        if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
1014
0
            if (!ctxt->check) {
1015
0
                xmlCtxtDumpSpaces(ctxt);
1016
0
                fprintf(ctxt->output, "content=");
1017
0
                xmlCtxtDumpString(ctxt, node->content);
1018
0
                fprintf(ctxt->output, "\n");
1019
0
            }
1020
0
        }
1021
0
    } else {
1022
0
        xmlEntityPtr ent;
1023
1024
0
        ent = xmlGetDocEntity(node->doc, node->name);
1025
0
        if (ent != NULL)
1026
0
            xmlCtxtDumpEntity(ctxt, ent);
1027
0
    }
1028
0
    ctxt->depth--;
1029
1030
    /*
1031
     * Do a bit of checking
1032
     */
1033
0
    xmlCtxtGenericNodeCheck(ctxt, node);
1034
0
}
1035
1036
/**
1037
 * xmlCtxtDumpNode:
1038
 * @output:  the FILE * for the output
1039
 * @node:  the node
1040
 * @depth:  the indentation level.
1041
 *
1042
 * Dumps debug information for the element node, it is recursive
1043
 */
1044
static void
1045
xmlCtxtDumpNode(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
1046
0
{
1047
0
    if (node == NULL) {
1048
0
        if (!ctxt->check) {
1049
0
            xmlCtxtDumpSpaces(ctxt);
1050
0
            fprintf(ctxt->output, "node is NULL\n");
1051
0
        }
1052
0
        return;
1053
0
    }
1054
0
    xmlCtxtDumpOneNode(ctxt, node);
1055
0
    if ((node->type != XML_NAMESPACE_DECL) &&
1056
0
        (node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
1057
0
        ctxt->depth++;
1058
0
        xmlCtxtDumpNodeList(ctxt, node->children);
1059
0
        ctxt->depth--;
1060
0
    }
1061
0
}
1062
1063
/**
1064
 * xmlCtxtDumpNodeList:
1065
 * @output:  the FILE * for the output
1066
 * @node:  the node list
1067
 * @depth:  the indentation level.
1068
 *
1069
 * Dumps debug information for the list of element node, it is recursive
1070
 */
1071
static void
1072
xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
1073
0
{
1074
0
    while (node != NULL) {
1075
0
        xmlCtxtDumpNode(ctxt, node);
1076
0
        node = node->next;
1077
0
    }
1078
0
}
1079
1080
static void
1081
xmlCtxtDumpDocHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1082
0
{
1083
0
    if (doc == NULL) {
1084
0
        if (!ctxt->check)
1085
0
            fprintf(ctxt->output, "DOCUMENT == NULL !\n");
1086
0
        return;
1087
0
    }
1088
0
    ctxt->node = (xmlNodePtr) doc;
1089
1090
0
    switch (doc->type) {
1091
0
        case XML_ELEMENT_NODE:
1092
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_ELEMENT,
1093
0
                  "Misplaced ELEMENT node\n");
1094
0
            break;
1095
0
        case XML_ATTRIBUTE_NODE:
1096
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_ATTRIBUTE,
1097
0
                  "Misplaced ATTRIBUTE node\n");
1098
0
            break;
1099
0
        case XML_TEXT_NODE:
1100
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_TEXT,
1101
0
                  "Misplaced TEXT node\n");
1102
0
            break;
1103
0
        case XML_CDATA_SECTION_NODE:
1104
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_CDATA,
1105
0
                  "Misplaced CDATA node\n");
1106
0
            break;
1107
0
        case XML_ENTITY_REF_NODE:
1108
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITYREF,
1109
0
                  "Misplaced ENTITYREF node\n");
1110
0
            break;
1111
0
        case XML_ENTITY_NODE:
1112
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITY,
1113
0
                  "Misplaced ENTITY node\n");
1114
0
            break;
1115
0
        case XML_PI_NODE:
1116
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_PI,
1117
0
                  "Misplaced PI node\n");
1118
0
            break;
1119
0
        case XML_COMMENT_NODE:
1120
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_COMMENT,
1121
0
                  "Misplaced COMMENT node\n");
1122
0
            break;
1123
0
        case XML_DOCUMENT_NODE:
1124
0
      if (!ctxt->check)
1125
0
    fprintf(ctxt->output, "DOCUMENT\n");
1126
0
            break;
1127
0
        case XML_HTML_DOCUMENT_NODE:
1128
0
      if (!ctxt->check)
1129
0
    fprintf(ctxt->output, "HTML DOCUMENT\n");
1130
0
            break;
1131
0
        case XML_DOCUMENT_TYPE_NODE:
1132
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_DOCTYPE,
1133
0
                  "Misplaced DOCTYPE node\n");
1134
0
            break;
1135
0
        case XML_DOCUMENT_FRAG_NODE:
1136
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_FRAGMENT,
1137
0
                  "Misplaced FRAGMENT node\n");
1138
0
            break;
1139
0
        case XML_NOTATION_NODE:
1140
0
      xmlDebugErr(ctxt, XML_CHECK_FOUND_NOTATION,
1141
0
                  "Misplaced NOTATION node\n");
1142
0
            break;
1143
0
        default:
1144
0
      xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE,
1145
0
                  "Unknown node type %d\n", doc->type);
1146
0
    }
1147
0
}
1148
1149
/**
1150
 * xmlCtxtDumpDocumentHead:
1151
 * @output:  the FILE * for the output
1152
 * @doc:  the document
1153
 *
1154
 * Dumps debug information concerning the document, not recursive
1155
 */
1156
static void
1157
xmlCtxtDumpDocumentHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1158
0
{
1159
0
    if (doc == NULL) return;
1160
0
    xmlCtxtDumpDocHead(ctxt, doc);
1161
0
    if (!ctxt->check) {
1162
0
        if (doc->name != NULL) {
1163
0
            fprintf(ctxt->output, "name=");
1164
0
            xmlCtxtDumpString(ctxt, BAD_CAST doc->name);
1165
0
            fprintf(ctxt->output, "\n");
1166
0
        }
1167
0
        if (doc->version != NULL) {
1168
0
            fprintf(ctxt->output, "version=");
1169
0
            xmlCtxtDumpString(ctxt, doc->version);
1170
0
            fprintf(ctxt->output, "\n");
1171
0
        }
1172
0
        if (doc->encoding != NULL) {
1173
0
            fprintf(ctxt->output, "encoding=");
1174
0
            xmlCtxtDumpString(ctxt, doc->encoding);
1175
0
            fprintf(ctxt->output, "\n");
1176
0
        }
1177
0
        if (doc->URL != NULL) {
1178
0
            fprintf(ctxt->output, "URL=");
1179
0
            xmlCtxtDumpString(ctxt, doc->URL);
1180
0
            fprintf(ctxt->output, "\n");
1181
0
        }
1182
0
        if (doc->standalone)
1183
0
            fprintf(ctxt->output, "standalone=true\n");
1184
0
    }
1185
0
    if (doc->oldNs != NULL)
1186
0
        xmlCtxtDumpNamespaceList(ctxt, doc->oldNs);
1187
0
}
1188
1189
/**
1190
 * xmlCtxtDumpDocument:
1191
 * @output:  the FILE * for the output
1192
 * @doc:  the document
1193
 *
1194
 * Dumps debug information for the document, it's recursive
1195
 */
1196
static void
1197
xmlCtxtDumpDocument(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1198
0
{
1199
0
    if (doc == NULL) {
1200
0
        if (!ctxt->check)
1201
0
            fprintf(ctxt->output, "DOCUMENT == NULL !\n");
1202
0
        return;
1203
0
    }
1204
0
    xmlCtxtDumpDocumentHead(ctxt, doc);
1205
0
    if (((doc->type == XML_DOCUMENT_NODE) ||
1206
0
         (doc->type == XML_HTML_DOCUMENT_NODE))
1207
0
        && (doc->children != NULL)) {
1208
0
        ctxt->depth++;
1209
0
        xmlCtxtDumpNodeList(ctxt, doc->children);
1210
0
        ctxt->depth--;
1211
0
    }
1212
0
}
1213
1214
static void
1215
xmlCtxtDumpEntityCallback(void *payload, void *data,
1216
                          const xmlChar *name ATTRIBUTE_UNUSED)
1217
0
{
1218
0
    xmlEntityPtr cur = (xmlEntityPtr) payload;
1219
0
    xmlDebugCtxtPtr ctxt = (xmlDebugCtxtPtr) data;
1220
0
    if (cur == NULL) {
1221
0
        if (!ctxt->check)
1222
0
            fprintf(ctxt->output, "Entity is NULL");
1223
0
        return;
1224
0
    }
1225
0
    if (!ctxt->check) {
1226
0
        fprintf(ctxt->output, "%s : ", (char *) cur->name);
1227
0
        switch (cur->etype) {
1228
0
            case XML_INTERNAL_GENERAL_ENTITY:
1229
0
                fprintf(ctxt->output, "INTERNAL GENERAL, ");
1230
0
                break;
1231
0
            case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1232
0
                fprintf(ctxt->output, "EXTERNAL PARSED, ");
1233
0
                break;
1234
0
            case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1235
0
                fprintf(ctxt->output, "EXTERNAL UNPARSED, ");
1236
0
                break;
1237
0
            case XML_INTERNAL_PARAMETER_ENTITY:
1238
0
                fprintf(ctxt->output, "INTERNAL PARAMETER, ");
1239
0
                break;
1240
0
            case XML_EXTERNAL_PARAMETER_ENTITY:
1241
0
                fprintf(ctxt->output, "EXTERNAL PARAMETER, ");
1242
0
                break;
1243
0
            default:
1244
0
    xmlDebugErr2(ctxt, XML_CHECK_ENTITY_TYPE,
1245
0
           "Unknown entity type %d\n", cur->etype);
1246
0
        }
1247
0
        if (cur->ExternalID != NULL)
1248
0
            fprintf(ctxt->output, "ID \"%s\"", (char *) cur->ExternalID);
1249
0
        if (cur->SystemID != NULL)
1250
0
            fprintf(ctxt->output, "SYSTEM \"%s\"", (char *) cur->SystemID);
1251
0
        if (cur->orig != NULL)
1252
0
            fprintf(ctxt->output, "\n orig \"%s\"", (char *) cur->orig);
1253
0
        if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL))
1254
0
            fprintf(ctxt->output, "\n content \"%s\"",
1255
0
                    (char *) cur->content);
1256
0
        fprintf(ctxt->output, "\n");
1257
0
    }
1258
0
}
1259
1260
/**
1261
 * xmlCtxtDumpEntities:
1262
 * @output:  the FILE * for the output
1263
 * @doc:  the document
1264
 *
1265
 * Dumps debug information for all the entities in use by the document
1266
 */
1267
static void
1268
xmlCtxtDumpEntities(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1269
0
{
1270
0
    if (doc == NULL) return;
1271
0
    xmlCtxtDumpDocHead(ctxt, doc);
1272
0
    if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
1273
0
        xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1274
0
            doc->intSubset->entities;
1275
1276
0
        if (!ctxt->check)
1277
0
            fprintf(ctxt->output, "Entities in internal subset\n");
1278
0
        xmlHashScan(table, xmlCtxtDumpEntityCallback, ctxt);
1279
0
    } else
1280
0
        fprintf(ctxt->output, "No entities in internal subset\n");
1281
0
    if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
1282
0
        xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1283
0
            doc->extSubset->entities;
1284
1285
0
        if (!ctxt->check)
1286
0
            fprintf(ctxt->output, "Entities in external subset\n");
1287
0
        xmlHashScan(table, xmlCtxtDumpEntityCallback, ctxt);
1288
0
    } else if (!ctxt->check)
1289
0
        fprintf(ctxt->output, "No entities in external subset\n");
1290
0
}
1291
1292
/**
1293
 * xmlCtxtDumpDTD:
1294
 * @output:  the FILE * for the output
1295
 * @dtd:  the DTD
1296
 *
1297
 * Dumps debug information for the DTD
1298
 */
1299
static void
1300
xmlCtxtDumpDTD(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd)
1301
0
{
1302
0
    if (dtd == NULL) {
1303
0
        if (!ctxt->check)
1304
0
            fprintf(ctxt->output, "DTD is NULL\n");
1305
0
        return;
1306
0
    }
1307
0
    xmlCtxtDumpDtdNode(ctxt, dtd);
1308
0
    if (dtd->children == NULL)
1309
0
        fprintf(ctxt->output, "    DTD is empty\n");
1310
0
    else {
1311
0
        ctxt->depth++;
1312
0
        xmlCtxtDumpNodeList(ctxt, dtd->children);
1313
0
        ctxt->depth--;
1314
0
    }
1315
0
}
1316
1317
/************************************************************************
1318
 *                  *
1319
 *      Public entry points for dump      *
1320
 *                  *
1321
 ************************************************************************/
1322
1323
/**
1324
 * xmlDebugDumpString:
1325
 * @output:  the FILE * for the output
1326
 * @str:  the string
1327
 *
1328
 * Dumps information about the string, shorten it if necessary
1329
 */
1330
void
1331
xmlDebugDumpString(FILE * output, const xmlChar * str)
1332
0
{
1333
0
    int i;
1334
1335
0
    if (output == NULL)
1336
0
  output = stdout;
1337
0
    if (str == NULL) {
1338
0
        fprintf(output, "(NULL)");
1339
0
        return;
1340
0
    }
1341
0
    for (i = 0; i < 40; i++)
1342
0
        if (str[i] == 0)
1343
0
            return;
1344
0
        else if (IS_BLANK_CH(str[i]))
1345
0
            fputc(' ', output);
1346
0
        else if (str[i] >= 0x80)
1347
0
            fprintf(output, "#%X", str[i]);
1348
0
        else
1349
0
            fputc(str[i], output);
1350
0
    fprintf(output, "...");
1351
0
}
1352
1353
/**
1354
 * xmlDebugDumpAttr:
1355
 * @output:  the FILE * for the output
1356
 * @attr:  the attribute
1357
 * @depth:  the indentation level.
1358
 *
1359
 * Dumps debug information for the attribute
1360
 */
1361
void
1362
0
xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
1363
0
    xmlDebugCtxt ctxt;
1364
1365
0
    if (output == NULL) return;
1366
0
    xmlCtxtDumpInitCtxt(&ctxt);
1367
0
    ctxt.output = output;
1368
0
    ctxt.depth = depth;
1369
0
    xmlCtxtDumpAttr(&ctxt, attr);
1370
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1371
0
}
1372
1373
1374
/**
1375
 * xmlDebugDumpEntities:
1376
 * @output:  the FILE * for the output
1377
 * @doc:  the document
1378
 *
1379
 * Dumps debug information for all the entities in use by the document
1380
 */
1381
void
1382
xmlDebugDumpEntities(FILE * output, xmlDocPtr doc)
1383
0
{
1384
0
    xmlDebugCtxt ctxt;
1385
1386
0
    if (output == NULL) return;
1387
0
    xmlCtxtDumpInitCtxt(&ctxt);
1388
0
    ctxt.output = output;
1389
0
    xmlCtxtDumpEntities(&ctxt, doc);
1390
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1391
0
}
1392
1393
/**
1394
 * xmlDebugDumpAttrList:
1395
 * @output:  the FILE * for the output
1396
 * @attr:  the attribute list
1397
 * @depth:  the indentation level.
1398
 *
1399
 * Dumps debug information for the attribute list
1400
 */
1401
void
1402
xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth)
1403
0
{
1404
0
    xmlDebugCtxt ctxt;
1405
1406
0
    if (output == NULL) return;
1407
0
    xmlCtxtDumpInitCtxt(&ctxt);
1408
0
    ctxt.output = output;
1409
0
    ctxt.depth = depth;
1410
0
    xmlCtxtDumpAttrList(&ctxt, attr);
1411
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1412
0
}
1413
1414
/**
1415
 * xmlDebugDumpOneNode:
1416
 * @output:  the FILE * for the output
1417
 * @node:  the node
1418
 * @depth:  the indentation level.
1419
 *
1420
 * Dumps debug information for the element node, it is not recursive
1421
 */
1422
void
1423
xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth)
1424
0
{
1425
0
    xmlDebugCtxt ctxt;
1426
1427
0
    if (output == NULL) return;
1428
0
    xmlCtxtDumpInitCtxt(&ctxt);
1429
0
    ctxt.output = output;
1430
0
    ctxt.depth = depth;
1431
0
    xmlCtxtDumpOneNode(&ctxt, node);
1432
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1433
0
}
1434
1435
/**
1436
 * xmlDebugDumpNode:
1437
 * @output:  the FILE * for the output
1438
 * @node:  the node
1439
 * @depth:  the indentation level.
1440
 *
1441
 * Dumps debug information for the element node, it is recursive
1442
 */
1443
void
1444
xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth)
1445
0
{
1446
0
    xmlDebugCtxt ctxt;
1447
1448
0
    if (output == NULL)
1449
0
  output = stdout;
1450
0
    xmlCtxtDumpInitCtxt(&ctxt);
1451
0
    ctxt.output = output;
1452
0
    ctxt.depth = depth;
1453
0
    xmlCtxtDumpNode(&ctxt, node);
1454
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1455
0
}
1456
1457
/**
1458
 * xmlDebugDumpNodeList:
1459
 * @output:  the FILE * for the output
1460
 * @node:  the node list
1461
 * @depth:  the indentation level.
1462
 *
1463
 * Dumps debug information for the list of element node, it is recursive
1464
 */
1465
void
1466
xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth)
1467
0
{
1468
0
    xmlDebugCtxt ctxt;
1469
1470
0
    if (output == NULL)
1471
0
  output = stdout;
1472
0
    xmlCtxtDumpInitCtxt(&ctxt);
1473
0
    ctxt.output = output;
1474
0
    ctxt.depth = depth;
1475
0
    xmlCtxtDumpNodeList(&ctxt, node);
1476
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1477
0
}
1478
1479
/**
1480
 * xmlDebugDumpDocumentHead:
1481
 * @output:  the FILE * for the output
1482
 * @doc:  the document
1483
 *
1484
 * Dumps debug information concerning the document, not recursive
1485
 */
1486
void
1487
xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc)
1488
0
{
1489
0
    xmlDebugCtxt ctxt;
1490
1491
0
    if (output == NULL)
1492
0
  output = stdout;
1493
0
    xmlCtxtDumpInitCtxt(&ctxt);
1494
0
    ctxt.options |= DUMP_TEXT_TYPE;
1495
0
    ctxt.output = output;
1496
0
    xmlCtxtDumpDocumentHead(&ctxt, doc);
1497
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1498
0
}
1499
1500
/**
1501
 * xmlDebugDumpDocument:
1502
 * @output:  the FILE * for the output
1503
 * @doc:  the document
1504
 *
1505
 * Dumps debug information for the document, it's recursive
1506
 */
1507
void
1508
xmlDebugDumpDocument(FILE * output, xmlDocPtr doc)
1509
0
{
1510
0
    xmlDebugCtxt ctxt;
1511
1512
0
    if (output == NULL)
1513
0
  output = stdout;
1514
0
    xmlCtxtDumpInitCtxt(&ctxt);
1515
0
    ctxt.options |= DUMP_TEXT_TYPE;
1516
0
    ctxt.output = output;
1517
0
    xmlCtxtDumpDocument(&ctxt, doc);
1518
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1519
0
}
1520
1521
/**
1522
 * xmlDebugDumpDTD:
1523
 * @output:  the FILE * for the output
1524
 * @dtd:  the DTD
1525
 *
1526
 * Dumps debug information for the DTD
1527
 */
1528
void
1529
xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd)
1530
0
{
1531
0
    xmlDebugCtxt ctxt;
1532
1533
0
    if (output == NULL)
1534
0
  output = stdout;
1535
0
    xmlCtxtDumpInitCtxt(&ctxt);
1536
0
    ctxt.options |= DUMP_TEXT_TYPE;
1537
0
    ctxt.output = output;
1538
0
    xmlCtxtDumpDTD(&ctxt, dtd);
1539
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1540
0
}
1541
1542
/************************************************************************
1543
 *                  *
1544
 *      Public entry points for checkings   *
1545
 *                  *
1546
 ************************************************************************/
1547
1548
/**
1549
 * xmlDebugCheckDocument:
1550
 * @output:  the FILE * for the output
1551
 * @doc:  the document
1552
 *
1553
 * Check the document for potential content problems, and output
1554
 * the errors to @output
1555
 *
1556
 * Returns the number of errors found
1557
 */
1558
int
1559
xmlDebugCheckDocument(FILE * output, xmlDocPtr doc)
1560
0
{
1561
0
    xmlDebugCtxt ctxt;
1562
1563
0
    if (output == NULL)
1564
0
  output = stdout;
1565
0
    xmlCtxtDumpInitCtxt(&ctxt);
1566
0
    ctxt.output = output;
1567
0
    ctxt.check = 1;
1568
0
    xmlCtxtDumpDocument(&ctxt, doc);
1569
0
    xmlCtxtDumpCleanCtxt(&ctxt);
1570
0
    return(ctxt.errors);
1571
0
}
1572
1573
/************************************************************************
1574
 *                  *
1575
 *      Helpers for Shell       *
1576
 *                  *
1577
 ************************************************************************/
1578
1579
/**
1580
 * xmlLsCountNode:
1581
 * @node:  the node to count
1582
 *
1583
 * Count the children of @node.
1584
 *
1585
 * Returns the number of children of @node.
1586
 */
1587
int
1588
0
xmlLsCountNode(xmlNodePtr node) {
1589
0
    int ret = 0;
1590
0
    xmlNodePtr list = NULL;
1591
1592
0
    if (node == NULL)
1593
0
  return(0);
1594
1595
0
    switch (node->type) {
1596
0
  case XML_ELEMENT_NODE:
1597
0
      list = node->children;
1598
0
      break;
1599
0
  case XML_DOCUMENT_NODE:
1600
0
  case XML_HTML_DOCUMENT_NODE:
1601
0
      list = ((xmlDocPtr) node)->children;
1602
0
      break;
1603
0
  case XML_ATTRIBUTE_NODE:
1604
0
      list = ((xmlAttrPtr) node)->children;
1605
0
      break;
1606
0
  case XML_TEXT_NODE:
1607
0
  case XML_CDATA_SECTION_NODE:
1608
0
  case XML_PI_NODE:
1609
0
  case XML_COMMENT_NODE:
1610
0
      if (node->content != NULL) {
1611
0
    ret = xmlStrlen(node->content);
1612
0
            }
1613
0
      break;
1614
0
  case XML_ENTITY_REF_NODE:
1615
0
  case XML_DOCUMENT_TYPE_NODE:
1616
0
  case XML_ENTITY_NODE:
1617
0
  case XML_DOCUMENT_FRAG_NODE:
1618
0
  case XML_NOTATION_NODE:
1619
0
  case XML_DTD_NODE:
1620
0
        case XML_ELEMENT_DECL:
1621
0
        case XML_ATTRIBUTE_DECL:
1622
0
        case XML_ENTITY_DECL:
1623
0
  case XML_NAMESPACE_DECL:
1624
0
  case XML_XINCLUDE_START:
1625
0
  case XML_XINCLUDE_END:
1626
0
      ret = 1;
1627
0
      break;
1628
0
    }
1629
0
    for (;list != NULL;ret++)
1630
0
        list = list->next;
1631
0
    return(ret);
1632
0
}
1633
1634
/**
1635
 * xmlLsOneNode:
1636
 * @output:  the FILE * for the output
1637
 * @node:  the node to dump
1638
 *
1639
 * Dump to @output the type and name of @node.
1640
 */
1641
void
1642
0
xmlLsOneNode(FILE *output, xmlNodePtr node) {
1643
0
    if (output == NULL) return;
1644
0
    if (node == NULL) {
1645
0
  fprintf(output, "NULL\n");
1646
0
  return;
1647
0
    }
1648
0
    switch (node->type) {
1649
0
  case XML_ELEMENT_NODE:
1650
0
      fprintf(output, "-");
1651
0
      break;
1652
0
  case XML_ATTRIBUTE_NODE:
1653
0
      fprintf(output, "a");
1654
0
      break;
1655
0
  case XML_TEXT_NODE:
1656
0
      fprintf(output, "t");
1657
0
      break;
1658
0
  case XML_CDATA_SECTION_NODE:
1659
0
      fprintf(output, "C");
1660
0
      break;
1661
0
  case XML_ENTITY_REF_NODE:
1662
0
      fprintf(output, "e");
1663
0
      break;
1664
0
  case XML_ENTITY_NODE:
1665
0
      fprintf(output, "E");
1666
0
      break;
1667
0
  case XML_PI_NODE:
1668
0
      fprintf(output, "p");
1669
0
      break;
1670
0
  case XML_COMMENT_NODE:
1671
0
      fprintf(output, "c");
1672
0
      break;
1673
0
  case XML_DOCUMENT_NODE:
1674
0
      fprintf(output, "d");
1675
0
      break;
1676
0
  case XML_HTML_DOCUMENT_NODE:
1677
0
      fprintf(output, "h");
1678
0
      break;
1679
0
  case XML_DOCUMENT_TYPE_NODE:
1680
0
      fprintf(output, "T");
1681
0
      break;
1682
0
  case XML_DOCUMENT_FRAG_NODE:
1683
0
      fprintf(output, "F");
1684
0
      break;
1685
0
  case XML_NOTATION_NODE:
1686
0
      fprintf(output, "N");
1687
0
      break;
1688
0
  case XML_NAMESPACE_DECL:
1689
0
      fprintf(output, "n");
1690
0
      break;
1691
0
  default:
1692
0
      fprintf(output, "?");
1693
0
    }
1694
0
    if (node->type != XML_NAMESPACE_DECL) {
1695
0
  if (node->properties != NULL)
1696
0
      fprintf(output, "a");
1697
0
  else
1698
0
      fprintf(output, "-");
1699
0
  if (node->nsDef != NULL)
1700
0
      fprintf(output, "n");
1701
0
  else
1702
0
      fprintf(output, "-");
1703
0
    }
1704
1705
0
    fprintf(output, " %8d ", xmlLsCountNode(node));
1706
1707
0
    switch (node->type) {
1708
0
  case XML_ELEMENT_NODE:
1709
0
      if (node->name != NULL) {
1710
0
                if ((node->ns != NULL) && (node->ns->prefix != NULL))
1711
0
                    fprintf(output, "%s:", node->ns->prefix);
1712
0
    fprintf(output, "%s", (const char *) node->name);
1713
0
            }
1714
0
      break;
1715
0
  case XML_ATTRIBUTE_NODE:
1716
0
      if (node->name != NULL)
1717
0
    fprintf(output, "%s", (const char *) node->name);
1718
0
      break;
1719
0
  case XML_TEXT_NODE:
1720
0
      if (node->content != NULL) {
1721
0
    xmlDebugDumpString(output, node->content);
1722
0
            }
1723
0
      break;
1724
0
  case XML_CDATA_SECTION_NODE:
1725
0
      break;
1726
0
  case XML_ENTITY_REF_NODE:
1727
0
      if (node->name != NULL)
1728
0
    fprintf(output, "%s", (const char *) node->name);
1729
0
      break;
1730
0
  case XML_ENTITY_NODE:
1731
0
      if (node->name != NULL)
1732
0
    fprintf(output, "%s", (const char *) node->name);
1733
0
      break;
1734
0
  case XML_PI_NODE:
1735
0
      if (node->name != NULL)
1736
0
    fprintf(output, "%s", (const char *) node->name);
1737
0
      break;
1738
0
  case XML_COMMENT_NODE:
1739
0
      break;
1740
0
  case XML_DOCUMENT_NODE:
1741
0
      break;
1742
0
  case XML_HTML_DOCUMENT_NODE:
1743
0
      break;
1744
0
  case XML_DOCUMENT_TYPE_NODE:
1745
0
      break;
1746
0
  case XML_DOCUMENT_FRAG_NODE:
1747
0
      break;
1748
0
  case XML_NOTATION_NODE:
1749
0
      break;
1750
0
  case XML_NAMESPACE_DECL: {
1751
0
      xmlNsPtr ns = (xmlNsPtr) node;
1752
1753
0
      if (ns->prefix == NULL)
1754
0
    fprintf(output, "default -> %s", (char *)ns->href);
1755
0
      else
1756
0
    fprintf(output, "%s -> %s", (char *)ns->prefix,
1757
0
      (char *)ns->href);
1758
0
      break;
1759
0
  }
1760
0
  default:
1761
0
      if (node->name != NULL)
1762
0
    fprintf(output, "%s", (const char *) node->name);
1763
0
    }
1764
0
    fprintf(output, "\n");
1765
0
}
1766
1767
/**
1768
 * xmlBoolToText:
1769
 * @boolval: a bool to turn into text
1770
 *
1771
 * Convenient way to turn bool into text
1772
 *
1773
 * Returns a pointer to either "True" or "False"
1774
 */
1775
const char *
1776
xmlBoolToText(int boolval)
1777
0
{
1778
0
    if (boolval)
1779
0
        return("True");
1780
0
    else
1781
0
        return("False");
1782
0
}
1783
1784
#ifdef LIBXML_XPATH_ENABLED
1785
/****************************************************************
1786
 *                *
1787
 *    The XML shell related functions     *
1788
 *                *
1789
 ****************************************************************/
1790
1791
1792
1793
/*
1794
 * TODO: Improvement/cleanups for the XML shell
1795
 *     - allow to shell out an editor on a subpart
1796
 *     - cleanup function registrations (with help) and calling
1797
 *     - provide registration routines
1798
 */
1799
1800
/**
1801
 * xmlShellPrintXPathError:
1802
 * @errorType: valid xpath error id
1803
 * @arg: the argument that cause xpath to fail
1804
 *
1805
 * Print the xpath error to libxml default error channel
1806
 */
1807
void
1808
xmlShellPrintXPathError(int errorType, const char *arg)
1809
0
{
1810
0
    const char *default_arg = "Result";
1811
1812
0
    if (!arg)
1813
0
        arg = default_arg;
1814
1815
0
    switch (errorType) {
1816
0
        case XPATH_UNDEFINED:
1817
0
            fprintf(stderr,
1818
0
                            "%s: no such node\n", arg);
1819
0
            break;
1820
1821
0
        case XPATH_BOOLEAN:
1822
0
            fprintf(stderr,
1823
0
                            "%s is a Boolean\n", arg);
1824
0
            break;
1825
0
        case XPATH_NUMBER:
1826
0
            fprintf(stderr,
1827
0
                            "%s is a number\n", arg);
1828
0
            break;
1829
0
        case XPATH_STRING:
1830
0
            fprintf(stderr,
1831
0
                            "%s is a string\n", arg);
1832
0
            break;
1833
#ifdef LIBXML_XPTR_LOCS_ENABLED
1834
        case XPATH_POINT:
1835
            fprintf(stderr,
1836
                            "%s is a point\n", arg);
1837
            break;
1838
        case XPATH_RANGE:
1839
            fprintf(stderr,
1840
                            "%s is a range\n", arg);
1841
            break;
1842
        case XPATH_LOCATIONSET:
1843
            fprintf(stderr,
1844
                            "%s is a range\n", arg);
1845
            break;
1846
#endif /* LIBXML_XPTR_LOCS_ENABLED */
1847
0
        case XPATH_USERS:
1848
0
            fprintf(stderr,
1849
0
                            "%s is user-defined\n", arg);
1850
0
            break;
1851
0
        case XPATH_XSLT_TREE:
1852
0
            fprintf(stderr,
1853
0
                            "%s is an XSLT value tree\n", arg);
1854
0
            break;
1855
0
    }
1856
#if 0
1857
    fprintf(stderr,
1858
                    "Try casting the result string function (xpath builtin)\n",
1859
                    arg);
1860
#endif
1861
0
}
1862
1863
1864
#ifdef LIBXML_OUTPUT_ENABLED
1865
/**
1866
 * xmlShellPrintNodeCtxt:
1867
 * @ctxt : a non-null shell context
1868
 * @node : a non-null node to print to the output FILE
1869
 *
1870
 * Print node to the output FILE
1871
 */
1872
static void
1873
xmlShellPrintNodeCtxt(xmlShellCtxtPtr ctxt,xmlNodePtr node)
1874
0
{
1875
0
    FILE *fp;
1876
1877
0
    if (!node)
1878
0
        return;
1879
0
    if (ctxt == NULL)
1880
0
  fp = stdout;
1881
0
    else
1882
0
  fp = ctxt->output;
1883
1884
0
    if (node->type == XML_DOCUMENT_NODE)
1885
0
        xmlDocDump(fp, (xmlDocPtr) node);
1886
0
    else if (node->type == XML_ATTRIBUTE_NODE)
1887
0
        xmlDebugDumpAttrList(fp, (xmlAttrPtr) node, 0);
1888
0
    else
1889
0
        xmlElemDump(fp, node->doc, node);
1890
1891
0
    fprintf(fp, "\n");
1892
0
}
1893
1894
/**
1895
 * xmlShellPrintNode:
1896
 * @node : a non-null node to print to the output FILE
1897
 *
1898
 * Print node to the output FILE
1899
 */
1900
void
1901
xmlShellPrintNode(xmlNodePtr node)
1902
0
{
1903
0
    xmlShellPrintNodeCtxt(NULL, node);
1904
0
}
1905
#endif /* LIBXML_OUTPUT_ENABLED */
1906
1907
/**
1908
 * xmlShellPrintXPathResultCtxt:
1909
 * @ctxt: a valid shell context
1910
 * @list: a valid result generated by an xpath evaluation
1911
 *
1912
 * Prints result to the output FILE
1913
 */
1914
static void
1915
xmlShellPrintXPathResultCtxt(xmlShellCtxtPtr ctxt,xmlXPathObjectPtr list)
1916
0
{
1917
0
    if (!ctxt)
1918
0
       return;
1919
1920
0
    if (list != NULL) {
1921
0
        switch (list->type) {
1922
0
            case XPATH_NODESET:{
1923
0
#ifdef LIBXML_OUTPUT_ENABLED
1924
0
                    int indx;
1925
1926
0
                    if (list->nodesetval) {
1927
0
                        for (indx = 0; indx < list->nodesetval->nodeNr;
1928
0
                             indx++) {
1929
0
                            xmlShellPrintNodeCtxt(ctxt,
1930
0
            list->nodesetval->nodeTab[indx]);
1931
0
                        }
1932
0
                    } else {
1933
0
                        fprintf(ctxt->output,
1934
0
                                        "Empty node set\n");
1935
0
                    }
1936
0
                    break;
1937
#else
1938
        fprintf(ctxt->output,
1939
            "Node set\n");
1940
#endif /* LIBXML_OUTPUT_ENABLED */
1941
0
                }
1942
0
            case XPATH_BOOLEAN:
1943
0
                fprintf(ctxt->output,
1944
0
                                "Is a Boolean:%s\n",
1945
0
                                xmlBoolToText(list->boolval));
1946
0
                break;
1947
0
            case XPATH_NUMBER:
1948
0
                fprintf(ctxt->output,
1949
0
                                "Is a number:%0g\n", list->floatval);
1950
0
                break;
1951
0
            case XPATH_STRING:
1952
0
                fprintf(ctxt->output,
1953
0
                                "Is a string:%s\n", list->stringval);
1954
0
                break;
1955
1956
0
            default:
1957
0
                xmlShellPrintXPathError(list->type, NULL);
1958
0
        }
1959
0
    }
1960
0
}
1961
1962
/**
1963
 * xmlShellPrintXPathResult:
1964
 * @list: a valid result generated by an xpath evaluation
1965
 *
1966
 * Prints result to the output FILE
1967
 */
1968
void
1969
xmlShellPrintXPathResult(xmlXPathObjectPtr list)
1970
0
{
1971
0
    xmlShellPrintXPathResultCtxt(NULL, list);
1972
0
}
1973
1974
/**
1975
 * xmlShellList:
1976
 * @ctxt:  the shell context
1977
 * @arg:  unused
1978
 * @node:  a node
1979
 * @node2:  unused
1980
 *
1981
 * Implements the XML shell function "ls"
1982
 * Does an Unix like listing of the given node (like a directory)
1983
 *
1984
 * Returns 0
1985
 */
1986
int
1987
xmlShellList(xmlShellCtxtPtr ctxt,
1988
             char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1989
             xmlNodePtr node2 ATTRIBUTE_UNUSED)
1990
0
{
1991
0
    xmlNodePtr cur;
1992
0
    if (!ctxt)
1993
0
        return (0);
1994
0
    if (node == NULL) {
1995
0
  fprintf(ctxt->output, "NULL\n");
1996
0
  return (0);
1997
0
    }
1998
0
    if ((node->type == XML_DOCUMENT_NODE) ||
1999
0
        (node->type == XML_HTML_DOCUMENT_NODE)) {
2000
0
        cur = ((xmlDocPtr) node)->children;
2001
0
    } else if (node->type == XML_NAMESPACE_DECL) {
2002
0
        xmlLsOneNode(ctxt->output, node);
2003
0
        return (0);
2004
0
    } else if (node->children != NULL) {
2005
0
        cur = node->children;
2006
0
    } else {
2007
0
        xmlLsOneNode(ctxt->output, node);
2008
0
        return (0);
2009
0
    }
2010
0
    while (cur != NULL) {
2011
0
        xmlLsOneNode(ctxt->output, cur);
2012
0
        cur = cur->next;
2013
0
    }
2014
0
    return (0);
2015
0
}
2016
2017
/**
2018
 * xmlShellBase:
2019
 * @ctxt:  the shell context
2020
 * @arg:  unused
2021
 * @node:  a node
2022
 * @node2:  unused
2023
 *
2024
 * Implements the XML shell function "base"
2025
 * dumps the current XML base of the node
2026
 *
2027
 * Returns 0
2028
 */
2029
int
2030
xmlShellBase(xmlShellCtxtPtr ctxt,
2031
             char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
2032
             xmlNodePtr node2 ATTRIBUTE_UNUSED)
2033
0
{
2034
0
    xmlChar *base;
2035
0
    if (!ctxt)
2036
0
        return 0;
2037
0
    if (node == NULL) {
2038
0
  fprintf(ctxt->output, "NULL\n");
2039
0
  return (0);
2040
0
    }
2041
2042
0
    base = xmlNodeGetBase(node->doc, node);
2043
2044
0
    if (base == NULL) {
2045
0
        fprintf(ctxt->output, " No base found !!!\n");
2046
0
    } else {
2047
0
        fprintf(ctxt->output, "%s\n", base);
2048
0
        xmlFree(base);
2049
0
    }
2050
0
    return (0);
2051
0
}
2052
2053
#ifdef LIBXML_TREE_ENABLED
2054
/**
2055
 * xmlShellSetBase:
2056
 * @ctxt:  the shell context
2057
 * @arg:  the new base
2058
 * @node:  a node
2059
 * @node2:  unused
2060
 *
2061
 * Implements the XML shell function "setbase"
2062
 * change the current XML base of the node
2063
 *
2064
 * Returns 0
2065
 */
2066
static int
2067
xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
2068
             char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
2069
             xmlNodePtr node2 ATTRIBUTE_UNUSED)
2070
0
{
2071
0
    xmlNodeSetBase(node, (xmlChar*) arg);
2072
0
    return (0);
2073
0
}
2074
#endif
2075
2076
#ifdef LIBXML_XPATH_ENABLED
2077
/**
2078
 * xmlShellRegisterNamespace:
2079
 * @ctxt:  the shell context
2080
 * @arg:  a string in prefix=nsuri format
2081
 * @node:  unused
2082
 * @node2:  unused
2083
 *
2084
 * Implements the XML shell function "setns"
2085
 * register/unregister a prefix=namespace pair
2086
 * on the XPath context
2087
 *
2088
 * Returns 0 on success and a negative value otherwise.
2089
 */
2090
static int
2091
xmlShellRegisterNamespace(xmlShellCtxtPtr ctxt, char *arg,
2092
      xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2093
0
{
2094
0
    xmlChar* nsListDup;
2095
0
    xmlChar* prefix;
2096
0
    xmlChar* href;
2097
0
    xmlChar* next;
2098
2099
0
    nsListDup = xmlStrdup((xmlChar *) arg);
2100
0
    next = nsListDup;
2101
0
    while(next != NULL) {
2102
  /* skip spaces */
2103
  /*while((*next) == ' ') next++;*/
2104
0
  if((*next) == '\0') break;
2105
2106
  /* find prefix */
2107
0
  prefix = next;
2108
0
  next = (xmlChar*)xmlStrchr(next, '=');
2109
0
  if(next == NULL) {
2110
0
      fprintf(ctxt->output, "setns: prefix=[nsuri] required\n");
2111
0
      xmlFree(nsListDup);
2112
0
      return(-1);
2113
0
  }
2114
0
  *(next++) = '\0';
2115
2116
  /* find href */
2117
0
  href = next;
2118
0
  next = (xmlChar*)xmlStrchr(next, ' ');
2119
0
  if(next != NULL) {
2120
0
      *(next++) = '\0';
2121
0
  }
2122
2123
  /* do register namespace */
2124
0
  if(xmlXPathRegisterNs(ctxt->pctxt, prefix, href) != 0) {
2125
0
      fprintf(ctxt->output,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", prefix, href);
2126
0
      xmlFree(nsListDup);
2127
0
      return(-1);
2128
0
  }
2129
0
    }
2130
2131
0
    xmlFree(nsListDup);
2132
0
    return(0);
2133
0
}
2134
/**
2135
 * xmlShellRegisterRootNamespaces:
2136
 * @ctxt:  the shell context
2137
 * @arg:  unused
2138
 * @node:  the root element
2139
 * @node2:  unused
2140
 *
2141
 * Implements the XML shell function "setrootns"
2142
 * which registers all namespaces declarations found on the root element.
2143
 *
2144
 * Returns 0 on success and a negative value otherwise.
2145
 */
2146
static int
2147
xmlShellRegisterRootNamespaces(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
2148
      xmlNodePtr root, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2149
0
{
2150
0
    xmlNsPtr ns;
2151
2152
0
    if ((root == NULL) || (root->type != XML_ELEMENT_NODE) ||
2153
0
        (root->nsDef == NULL) || (ctxt == NULL) || (ctxt->pctxt == NULL))
2154
0
  return(-1);
2155
0
    ns = root->nsDef;
2156
0
    while (ns != NULL) {
2157
0
        if (ns->prefix == NULL)
2158
0
      xmlXPathRegisterNs(ctxt->pctxt, BAD_CAST "defaultns", ns->href);
2159
0
  else
2160
0
      xmlXPathRegisterNs(ctxt->pctxt, ns->prefix, ns->href);
2161
0
        ns = ns->next;
2162
0
    }
2163
0
    return(0);
2164
0
}
2165
#endif
2166
2167
/**
2168
 * xmlShellGrep:
2169
 * @ctxt:  the shell context
2170
 * @arg:  the string or regular expression to find
2171
 * @node:  a node
2172
 * @node2:  unused
2173
 *
2174
 * Implements the XML shell function "grep"
2175
 * dumps information about the node (namespace, attributes, content).
2176
 *
2177
 * Returns 0
2178
 */
2179
static int
2180
xmlShellGrep(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
2181
            char *arg, xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2182
0
{
2183
0
    if (!ctxt)
2184
0
        return (0);
2185
0
    if (node == NULL)
2186
0
  return (0);
2187
0
    if (arg == NULL)
2188
0
  return (0);
2189
0
#ifdef LIBXML_REGEXP_ENABLED
2190
0
    if ((xmlStrchr((xmlChar *) arg, '?')) ||
2191
0
  (xmlStrchr((xmlChar *) arg, '*')) ||
2192
0
  (xmlStrchr((xmlChar *) arg, '.')) ||
2193
0
  (xmlStrchr((xmlChar *) arg, '['))) {
2194
0
    }
2195
0
#endif
2196
0
    while (node != NULL) {
2197
0
        if (node->type == XML_COMMENT_NODE) {
2198
0
      if (xmlStrstr(node->content, (xmlChar *) arg)) {
2199
2200
0
    fprintf(ctxt->output, "%s : ", xmlGetNodePath(node));
2201
0
                xmlShellList(ctxt, NULL, node, NULL);
2202
0
      }
2203
0
        } else if (node->type == XML_TEXT_NODE) {
2204
0
      if (xmlStrstr(node->content, (xmlChar *) arg)) {
2205
2206
0
    fprintf(ctxt->output, "%s : ", xmlGetNodePath(node->parent));
2207
0
                xmlShellList(ctxt, NULL, node->parent, NULL);
2208
0
      }
2209
0
        }
2210
2211
        /*
2212
         * Browse the full subtree, deep first
2213
         */
2214
2215
0
        if ((node->type == XML_DOCUMENT_NODE) ||
2216
0
            (node->type == XML_HTML_DOCUMENT_NODE)) {
2217
0
            node = ((xmlDocPtr) node)->children;
2218
0
        } else if ((node->children != NULL)
2219
0
                   && (node->type != XML_ENTITY_REF_NODE)) {
2220
            /* deep first */
2221
0
            node = node->children;
2222
0
        } else if (node->next != NULL) {
2223
            /* then siblings */
2224
0
            node = node->next;
2225
0
        } else {
2226
            /* go up to parents->next if needed */
2227
0
            while (node != NULL) {
2228
0
                if (node->parent != NULL) {
2229
0
                    node = node->parent;
2230
0
                }
2231
0
                if (node->next != NULL) {
2232
0
                    node = node->next;
2233
0
                    break;
2234
0
                }
2235
0
                if (node->parent == NULL) {
2236
0
                    node = NULL;
2237
0
                    break;
2238
0
                }
2239
0
            }
2240
0
  }
2241
0
    }
2242
0
    return (0);
2243
0
}
2244
2245
/**
2246
 * xmlShellDir:
2247
 * @ctxt:  the shell context
2248
 * @arg:  unused
2249
 * @node:  a node
2250
 * @node2:  unused
2251
 *
2252
 * Implements the XML shell function "dir"
2253
 * dumps information about the node (namespace, attributes, content).
2254
 *
2255
 * Returns 0
2256
 */
2257
int
2258
xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
2259
            char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
2260
            xmlNodePtr node2 ATTRIBUTE_UNUSED)
2261
0
{
2262
0
    if (!ctxt)
2263
0
        return (0);
2264
0
    if (node == NULL) {
2265
0
  fprintf(ctxt->output, "NULL\n");
2266
0
  return (0);
2267
0
    }
2268
0
    if ((node->type == XML_DOCUMENT_NODE) ||
2269
0
        (node->type == XML_HTML_DOCUMENT_NODE)) {
2270
0
        xmlDebugDumpDocumentHead(ctxt->output, (xmlDocPtr) node);
2271
0
    } else if (node->type == XML_ATTRIBUTE_NODE) {
2272
0
        xmlDebugDumpAttr(ctxt->output, (xmlAttrPtr) node, 0);
2273
0
    } else {
2274
0
        xmlDebugDumpOneNode(ctxt->output, node, 0);
2275
0
    }
2276
0
    return (0);
2277
0
}
2278
2279
/**
2280
 * xmlShellSetContent:
2281
 * @ctxt:  the shell context
2282
 * @value:  the content as a string
2283
 * @node:  a node
2284
 * @node2:  unused
2285
 *
2286
 * Implements the XML shell function "dir"
2287
 * dumps information about the node (namespace, attributes, content).
2288
 *
2289
 * Returns 0
2290
 */
2291
static int
2292
xmlShellSetContent(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
2293
            char *value, xmlNodePtr node,
2294
            xmlNodePtr node2 ATTRIBUTE_UNUSED)
2295
0
{
2296
0
    xmlNodePtr results;
2297
0
    xmlParserErrors ret;
2298
2299
0
    if (!ctxt)
2300
0
        return (0);
2301
0
    if (node == NULL) {
2302
0
  fprintf(ctxt->output, "NULL\n");
2303
0
  return (0);
2304
0
    }
2305
0
    if (value == NULL) {
2306
0
        fprintf(ctxt->output, "NULL\n");
2307
0
  return (0);
2308
0
    }
2309
2310
0
    ret = xmlParseInNodeContext(node, value, strlen(value), 0, &results);
2311
0
    if (ret == XML_ERR_OK) {
2312
0
  if (node->children != NULL) {
2313
0
      xmlFreeNodeList(node->children);
2314
0
      node->children = NULL;
2315
0
      node->last = NULL;
2316
0
  }
2317
0
  xmlAddChildList(node, results);
2318
0
    } else {
2319
0
        fprintf(ctxt->output, "failed to parse content\n");
2320
0
    }
2321
0
    return (0);
2322
0
}
2323
2324
static void
2325
0
xmlShellPrintf(void *ctx, const char *msg, ...) {
2326
0
    xmlShellCtxtPtr sctxt = ctx;
2327
0
    va_list ap;
2328
2329
0
    va_start(ap, msg);
2330
0
    vfprintf(sctxt->output, msg, ap);
2331
0
    va_end(ap);
2332
0
}
2333
2334
#ifdef LIBXML_SCHEMAS_ENABLED
2335
/**
2336
 * xmlShellRNGValidate:
2337
 * @ctxt:  the shell context
2338
 * @schemas:  the path to the Relax-NG schemas
2339
 * @node:  a node
2340
 * @node2:  unused
2341
 *
2342
 * Implements the XML shell function "relaxng"
2343
 * validating the instance against a Relax-NG schemas
2344
 *
2345
 * Returns 0
2346
 */
2347
static int
2348
xmlShellRNGValidate(xmlShellCtxtPtr sctxt, char *schemas,
2349
            xmlNodePtr node ATTRIBUTE_UNUSED,
2350
      xmlNodePtr node2 ATTRIBUTE_UNUSED)
2351
0
{
2352
0
    xmlRelaxNGPtr relaxngschemas;
2353
0
    xmlRelaxNGParserCtxtPtr ctxt;
2354
0
    xmlRelaxNGValidCtxtPtr vctxt;
2355
0
    int ret;
2356
2357
0
    ctxt = xmlRelaxNGNewParserCtxt(schemas);
2358
0
    xmlRelaxNGSetParserErrors(ctxt, xmlShellPrintf, xmlShellPrintf, sctxt);
2359
0
    relaxngschemas = xmlRelaxNGParse(ctxt);
2360
0
    xmlRelaxNGFreeParserCtxt(ctxt);
2361
0
    if (relaxngschemas == NULL) {
2362
0
  fprintf(sctxt->output,
2363
0
    "Relax-NG schema %s failed to compile\n", schemas);
2364
0
  return(-1);
2365
0
    }
2366
0
    vctxt = xmlRelaxNGNewValidCtxt(relaxngschemas);
2367
0
    xmlRelaxNGSetValidErrors(vctxt, xmlShellPrintf, xmlShellPrintf, sctxt);
2368
0
    ret = xmlRelaxNGValidateDoc(vctxt, sctxt->doc);
2369
0
    if (ret == 0) {
2370
0
  fprintf(sctxt->output, "%s validates\n", sctxt->filename);
2371
0
    } else if (ret > 0) {
2372
0
  fprintf(sctxt->output, "%s fails to validate\n", sctxt->filename);
2373
0
    } else {
2374
0
  fprintf(sctxt->output, "%s validation generated an internal error\n",
2375
0
         sctxt->filename);
2376
0
    }
2377
0
    xmlRelaxNGFreeValidCtxt(vctxt);
2378
0
    if (relaxngschemas != NULL)
2379
0
  xmlRelaxNGFree(relaxngschemas);
2380
0
    return(0);
2381
0
}
2382
#endif
2383
2384
#ifdef LIBXML_OUTPUT_ENABLED
2385
/**
2386
 * xmlShellCat:
2387
 * @ctxt:  the shell context
2388
 * @arg:  unused
2389
 * @node:  a node
2390
 * @node2:  unused
2391
 *
2392
 * Implements the XML shell function "cat"
2393
 * dumps the serialization node content (XML or HTML).
2394
 *
2395
 * Returns 0
2396
 */
2397
int
2398
xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
2399
            xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2400
0
{
2401
0
    if (!ctxt)
2402
0
        return (0);
2403
0
    if (node == NULL) {
2404
0
  fprintf(ctxt->output, "NULL\n");
2405
0
  return (0);
2406
0
    }
2407
0
    if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
2408
0
#ifdef LIBXML_HTML_ENABLED
2409
0
        if (node->type == XML_HTML_DOCUMENT_NODE)
2410
0
            htmlDocDump(ctxt->output, (htmlDocPtr) node);
2411
0
        else
2412
0
            htmlNodeDumpFile(ctxt->output, ctxt->doc, node);
2413
#else
2414
        if (node->type == XML_DOCUMENT_NODE)
2415
            xmlDocDump(ctxt->output, (xmlDocPtr) node);
2416
        else
2417
            xmlElemDump(ctxt->output, ctxt->doc, node);
2418
#endif /* LIBXML_HTML_ENABLED */
2419
0
    } else {
2420
0
        if (node->type == XML_DOCUMENT_NODE)
2421
0
            xmlDocDump(ctxt->output, (xmlDocPtr) node);
2422
0
        else
2423
0
            xmlElemDump(ctxt->output, ctxt->doc, node);
2424
0
    }
2425
0
    fprintf(ctxt->output, "\n");
2426
0
    return (0);
2427
0
}
2428
#endif /* LIBXML_OUTPUT_ENABLED */
2429
2430
/**
2431
 * xmlShellLoad:
2432
 * @ctxt:  the shell context
2433
 * @filename:  the file name
2434
 * @node:  unused
2435
 * @node2:  unused
2436
 *
2437
 * Implements the XML shell function "load"
2438
 * loads a new document specified by the filename
2439
 *
2440
 * Returns 0 or -1 if loading failed
2441
 */
2442
int
2443
xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename,
2444
             xmlNodePtr node ATTRIBUTE_UNUSED,
2445
             xmlNodePtr node2 ATTRIBUTE_UNUSED)
2446
0
{
2447
0
    xmlDocPtr doc;
2448
0
    int html = 0;
2449
2450
0
    if ((ctxt == NULL) || (filename == NULL)) return(-1);
2451
0
    if (ctxt->doc != NULL)
2452
0
        html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
2453
2454
0
    if (html) {
2455
0
#ifdef LIBXML_HTML_ENABLED
2456
0
        doc = htmlParseFile(filename, NULL);
2457
#else
2458
        fprintf(ctxt->output, "HTML support not compiled in\n");
2459
        doc = NULL;
2460
#endif /* LIBXML_HTML_ENABLED */
2461
0
    } else {
2462
0
        doc = xmlReadFile(filename,NULL,0);
2463
0
    }
2464
0
    if (doc != NULL) {
2465
0
        if (ctxt->loaded == 1) {
2466
0
            xmlFreeDoc(ctxt->doc);
2467
0
        }
2468
0
        ctxt->loaded = 1;
2469
0
#ifdef LIBXML_XPATH_ENABLED
2470
0
        xmlXPathFreeContext(ctxt->pctxt);
2471
0
#endif /* LIBXML_XPATH_ENABLED */
2472
0
        xmlFree(ctxt->filename);
2473
0
        ctxt->doc = doc;
2474
0
        ctxt->node = (xmlNodePtr) doc;
2475
0
#ifdef LIBXML_XPATH_ENABLED
2476
0
        ctxt->pctxt = xmlXPathNewContext(doc);
2477
0
#endif /* LIBXML_XPATH_ENABLED */
2478
0
        ctxt->filename = (char *) xmlCanonicPath((xmlChar *) filename);
2479
0
    } else
2480
0
        return (-1);
2481
0
    return (0);
2482
0
}
2483
2484
#ifdef LIBXML_OUTPUT_ENABLED
2485
/**
2486
 * xmlShellWrite:
2487
 * @ctxt:  the shell context
2488
 * @filename:  the file name
2489
 * @node:  a node in the tree
2490
 * @node2:  unused
2491
 *
2492
 * Implements the XML shell function "write"
2493
 * Write the current node to the filename, it saves the serialization
2494
 * of the subtree under the @node specified
2495
 *
2496
 * Returns 0 or -1 in case of error
2497
 */
2498
int
2499
xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
2500
              xmlNodePtr node2 ATTRIBUTE_UNUSED)
2501
0
{
2502
0
    if (node == NULL)
2503
0
        return (-1);
2504
0
    if ((filename == NULL) || (filename[0] == 0)) {
2505
0
        return (-1);
2506
0
    }
2507
#ifdef W_OK
2508
    if (access((char *) filename, W_OK)) {
2509
        fprintf(ctxt->output,
2510
                        "Cannot write to %s\n", filename);
2511
        return (-1);
2512
    }
2513
#endif
2514
0
    switch (node->type) {
2515
0
        case XML_DOCUMENT_NODE:
2516
0
            if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
2517
0
                fprintf(ctxt->output,
2518
0
                                "Failed to write to %s\n", filename);
2519
0
                return (-1);
2520
0
            }
2521
0
            break;
2522
0
        case XML_HTML_DOCUMENT_NODE:
2523
0
#ifdef LIBXML_HTML_ENABLED
2524
0
            if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
2525
0
                fprintf(ctxt->output,
2526
0
                                "Failed to write to %s\n", filename);
2527
0
                return (-1);
2528
0
            }
2529
#else
2530
            if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
2531
                fprintf(ctxt->output,
2532
                                "Failed to write to %s\n", filename);
2533
                return (-1);
2534
            }
2535
#endif /* LIBXML_HTML_ENABLED */
2536
0
            break;
2537
0
        default:{
2538
0
                FILE *f;
2539
2540
0
                f = fopen((char *) filename, "w");
2541
0
                if (f == NULL) {
2542
0
                    fprintf(ctxt->output,
2543
0
                                    "Failed to write to %s\n", filename);
2544
0
                    return (-1);
2545
0
                }
2546
0
                xmlElemDump(f, ctxt->doc, node);
2547
0
                fclose(f);
2548
0
            }
2549
0
    }
2550
0
    return (0);
2551
0
}
2552
2553
/**
2554
 * xmlShellSave:
2555
 * @ctxt:  the shell context
2556
 * @filename:  the file name (optional)
2557
 * @node:  unused
2558
 * @node2:  unused
2559
 *
2560
 * Implements the XML shell function "save"
2561
 * Write the current document to the filename, or it's original name
2562
 *
2563
 * Returns 0 or -1 in case of error
2564
 */
2565
int
2566
xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
2567
             xmlNodePtr node ATTRIBUTE_UNUSED,
2568
             xmlNodePtr node2 ATTRIBUTE_UNUSED)
2569
0
{
2570
0
    if ((ctxt == NULL) || (ctxt->doc == NULL))
2571
0
        return (-1);
2572
0
    if ((filename == NULL) || (filename[0] == 0))
2573
0
        filename = ctxt->filename;
2574
0
    if (filename == NULL)
2575
0
        return (-1);
2576
#ifdef W_OK
2577
    if (access((char *) filename, W_OK)) {
2578
        fprintf(ctxt->output,
2579
                        "Cannot save to %s\n", filename);
2580
        return (-1);
2581
    }
2582
#endif
2583
0
    switch (ctxt->doc->type) {
2584
0
        case XML_DOCUMENT_NODE:
2585
0
            if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
2586
0
                fprintf(ctxt->output,
2587
0
                                "Failed to save to %s\n", filename);
2588
0
            }
2589
0
            break;
2590
0
        case XML_HTML_DOCUMENT_NODE:
2591
0
#ifdef LIBXML_HTML_ENABLED
2592
0
            if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
2593
0
                fprintf(ctxt->output,
2594
0
                                "Failed to save to %s\n", filename);
2595
0
            }
2596
#else
2597
            if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
2598
                fprintf(ctxt->output,
2599
                                "Failed to save to %s\n", filename);
2600
            }
2601
#endif /* LIBXML_HTML_ENABLED */
2602
0
            break;
2603
0
        default:
2604
0
            fprintf(ctxt->output,
2605
0
      "To save to subparts of a document use the 'write' command\n");
2606
0
            return (-1);
2607
2608
0
    }
2609
0
    return (0);
2610
0
}
2611
#endif /* LIBXML_OUTPUT_ENABLED */
2612
2613
#ifdef LIBXML_VALID_ENABLED
2614
/**
2615
 * xmlShellValidate:
2616
 * @ctxt:  the shell context
2617
 * @dtd:  the DTD URI (optional)
2618
 * @node:  unused
2619
 * @node2:  unused
2620
 *
2621
 * Implements the XML shell function "validate"
2622
 * Validate the document, if a DTD path is provided, then the validation
2623
 * is done against the given DTD.
2624
 *
2625
 * Returns 0 or -1 in case of error
2626
 */
2627
int
2628
xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd,
2629
                 xmlNodePtr node ATTRIBUTE_UNUSED,
2630
                 xmlNodePtr node2 ATTRIBUTE_UNUSED)
2631
0
{
2632
0
    xmlValidCtxt vctxt;
2633
0
    int res = -1;
2634
2635
0
    if ((ctxt == NULL) || (ctxt->doc == NULL)) return(-1);
2636
0
    memset(&vctxt, 0, sizeof(vctxt));
2637
0
    vctxt.error = xmlShellPrintf;
2638
0
    vctxt.warning = xmlShellPrintf;
2639
0
    vctxt.userData = ctxt;
2640
2641
0
    if ((dtd == NULL) || (dtd[0] == 0)) {
2642
0
        res = xmlValidateDocument(&vctxt, ctxt->doc);
2643
0
    } else {
2644
0
        xmlDtdPtr subset;
2645
2646
0
        subset = xmlParseDTD(NULL, (xmlChar *) dtd);
2647
0
        if (subset != NULL) {
2648
0
            res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
2649
2650
0
            xmlFreeDtd(subset);
2651
0
        }
2652
0
    }
2653
0
    return (res);
2654
0
}
2655
#endif /* LIBXML_VALID_ENABLED */
2656
2657
/**
2658
 * xmlShellDu:
2659
 * @ctxt:  the shell context
2660
 * @arg:  unused
2661
 * @tree:  a node defining a subtree
2662
 * @node2:  unused
2663
 *
2664
 * Implements the XML shell function "du"
2665
 * show the structure of the subtree under node @tree
2666
 * If @tree is null, the command works on the current node.
2667
 *
2668
 * Returns 0 or -1 in case of error
2669
 */
2670
int
2671
xmlShellDu(xmlShellCtxtPtr ctxt,
2672
           char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree,
2673
           xmlNodePtr node2 ATTRIBUTE_UNUSED)
2674
0
{
2675
0
    xmlNodePtr node;
2676
0
    int indent = 0, i;
2677
2678
0
    if (!ctxt)
2679
0
  return (-1);
2680
2681
0
    if (tree == NULL)
2682
0
        return (-1);
2683
0
    node = tree;
2684
0
    while (node != NULL) {
2685
0
        if ((node->type == XML_DOCUMENT_NODE) ||
2686
0
            (node->type == XML_HTML_DOCUMENT_NODE)) {
2687
0
            fprintf(ctxt->output, "/\n");
2688
0
        } else if (node->type == XML_ELEMENT_NODE) {
2689
0
            for (i = 0; i < indent; i++)
2690
0
                fprintf(ctxt->output, "  ");
2691
0
            if ((node->ns) && (node->ns->prefix))
2692
0
                fprintf(ctxt->output, "%s:", node->ns->prefix);
2693
0
            fprintf(ctxt->output, "%s\n", node->name);
2694
0
        } else {
2695
0
        }
2696
2697
        /*
2698
         * Browse the full subtree, deep first
2699
         */
2700
2701
0
        if ((node->type == XML_DOCUMENT_NODE) ||
2702
0
            (node->type == XML_HTML_DOCUMENT_NODE)) {
2703
0
            node = ((xmlDocPtr) node)->children;
2704
0
        } else if ((node->children != NULL)
2705
0
                   && (node->type != XML_ENTITY_REF_NODE)) {
2706
            /* deep first */
2707
0
            node = node->children;
2708
0
            indent++;
2709
0
        } else if ((node != tree) && (node->next != NULL)) {
2710
            /* then siblings */
2711
0
            node = node->next;
2712
0
        } else if (node != tree) {
2713
            /* go up to parents->next if needed */
2714
0
            while (node != tree) {
2715
0
                if (node->parent != NULL) {
2716
0
                    node = node->parent;
2717
0
                    indent--;
2718
0
                }
2719
0
                if ((node != tree) && (node->next != NULL)) {
2720
0
                    node = node->next;
2721
0
                    break;
2722
0
                }
2723
0
                if (node->parent == NULL) {
2724
0
                    node = NULL;
2725
0
                    break;
2726
0
                }
2727
0
                if (node == tree) {
2728
0
                    node = NULL;
2729
0
                    break;
2730
0
                }
2731
0
            }
2732
            /* exit condition */
2733
0
            if (node == tree)
2734
0
                node = NULL;
2735
0
        } else
2736
0
            node = NULL;
2737
0
    }
2738
0
    return (0);
2739
0
}
2740
2741
/**
2742
 * xmlShellPwd:
2743
 * @ctxt:  the shell context
2744
 * @buffer:  the output buffer
2745
 * @node:  a node
2746
 * @node2:  unused
2747
 *
2748
 * Implements the XML shell function "pwd"
2749
 * Show the full path from the root to the node, if needed building
2750
 * thumblers when similar elements exists at a given ancestor level.
2751
 * The output is compatible with XPath commands.
2752
 *
2753
 * Returns 0 or -1 in case of error
2754
 */
2755
int
2756
xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
2757
            xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2758
0
{
2759
0
    xmlChar *path;
2760
2761
0
    if ((node == NULL) || (buffer == NULL))
2762
0
        return (-1);
2763
2764
0
    path = xmlGetNodePath(node);
2765
0
    if (path == NULL)
2766
0
  return (-1);
2767
2768
    /*
2769
     * This test prevents buffer overflow, because this routine
2770
     * is only called by xmlShell, in which the second argument is
2771
     * 500 chars long.
2772
     * It is a dirty hack before a cleaner solution is found.
2773
     * Documentation should mention that the second argument must
2774
     * be at least 500 chars long, and could be stripped if too long.
2775
     */
2776
0
    snprintf(buffer, 499, "%s", path);
2777
0
    buffer[499] = '0';
2778
0
    xmlFree(path);
2779
2780
0
    return (0);
2781
0
}
2782
2783
/**
2784
 * xmlShell:
2785
 * @doc:  the initial document
2786
 * @filename:  the output buffer
2787
 * @input:  the line reading function
2788
 * @output:  the output FILE*, defaults to stdout if NULL
2789
 *
2790
 * Implements the XML shell
2791
 * This allow to load, validate, view, modify and save a document
2792
 * using a environment similar to a UNIX commandline.
2793
 */
2794
void
2795
xmlShell(xmlDocPtr doc, const char *filename, xmlShellReadlineFunc input,
2796
         FILE * output)
2797
0
{
2798
0
    char prompt[500] = "/ > ";
2799
0
    char *cmdline = NULL, *cur;
2800
0
    char command[100];
2801
0
    char arg[400];
2802
0
    int i;
2803
0
    xmlShellCtxtPtr ctxt;
2804
0
    xmlXPathObjectPtr list;
2805
2806
0
    if (doc == NULL)
2807
0
        return;
2808
0
    if (filename == NULL)
2809
0
        return;
2810
0
    if (input == NULL)
2811
0
        return;
2812
0
    if (output == NULL)
2813
0
        output = stdout;
2814
0
    ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
2815
0
    if (ctxt == NULL)
2816
0
        return;
2817
0
    ctxt->loaded = 0;
2818
0
    ctxt->doc = doc;
2819
0
    ctxt->input = input;
2820
0
    ctxt->output = output;
2821
0
    ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
2822
0
    ctxt->node = (xmlNodePtr) ctxt->doc;
2823
2824
0
#ifdef LIBXML_XPATH_ENABLED
2825
0
    ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
2826
0
    if (ctxt->pctxt == NULL) {
2827
0
        xmlFree(ctxt);
2828
0
        return;
2829
0
    }
2830
0
#endif /* LIBXML_XPATH_ENABLED */
2831
0
    while (1) {
2832
0
        if (ctxt->node == (xmlNodePtr) ctxt->doc)
2833
0
            snprintf(prompt, sizeof(prompt), "%s > ", "/");
2834
0
        else if ((ctxt->node != NULL) && (ctxt->node->name) &&
2835
0
                 (ctxt->node->ns) && (ctxt->node->ns->prefix))
2836
0
            snprintf(prompt, sizeof(prompt), "%s:%s > ",
2837
0
                     (ctxt->node->ns->prefix), ctxt->node->name);
2838
0
        else if ((ctxt->node != NULL) && (ctxt->node->name))
2839
0
            snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
2840
0
        else
2841
0
            snprintf(prompt, sizeof(prompt), "? > ");
2842
0
        prompt[sizeof(prompt) - 1] = 0;
2843
2844
        /*
2845
         * Get a new command line
2846
         */
2847
0
        cmdline = ctxt->input(prompt);
2848
0
        if (cmdline == NULL)
2849
0
            break;
2850
2851
        /*
2852
         * Parse the command itself
2853
         */
2854
0
        cur = cmdline;
2855
0
        while ((*cur == ' ') || (*cur == '\t'))
2856
0
            cur++;
2857
0
        i = 0;
2858
0
        while ((*cur != ' ') && (*cur != '\t') &&
2859
0
               (*cur != '\n') && (*cur != '\r')) {
2860
0
            if (*cur == 0)
2861
0
                break;
2862
0
            command[i++] = *cur++;
2863
0
        }
2864
0
        command[i] = 0;
2865
0
        if (i == 0)
2866
0
            continue;
2867
2868
        /*
2869
         * Parse the argument
2870
         */
2871
0
        while ((*cur == ' ') || (*cur == '\t'))
2872
0
            cur++;
2873
0
        i = 0;
2874
0
        while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
2875
0
            if (*cur == 0)
2876
0
                break;
2877
0
            arg[i++] = *cur++;
2878
0
        }
2879
0
        arg[i] = 0;
2880
2881
        /*
2882
         * start interpreting the command
2883
         */
2884
0
        if (!strcmp(command, "exit"))
2885
0
            break;
2886
0
        if (!strcmp(command, "quit"))
2887
0
            break;
2888
0
        if (!strcmp(command, "bye"))
2889
0
            break;
2890
0
    if (!strcmp(command, "help")) {
2891
0
      fprintf(ctxt->output, "\tbase         display XML base of the node\n");
2892
0
      fprintf(ctxt->output, "\tsetbase URI  change the XML base of the node\n");
2893
0
      fprintf(ctxt->output, "\tbye          leave shell\n");
2894
0
      fprintf(ctxt->output, "\tcat [node]   display node or current node\n");
2895
0
      fprintf(ctxt->output, "\tcd [path]    change directory to path or to root\n");
2896
0
      fprintf(ctxt->output, "\tdir [path]   dumps information about the node (namespace, attributes, content)\n");
2897
0
      fprintf(ctxt->output, "\tdu [path]    show the structure of the subtree under path or the current node\n");
2898
0
      fprintf(ctxt->output, "\texit         leave shell\n");
2899
0
      fprintf(ctxt->output, "\thelp         display this help\n");
2900
0
      fprintf(ctxt->output, "\tfree         display memory usage\n");
2901
0
      fprintf(ctxt->output, "\tload [name]  load a new document with name\n");
2902
0
      fprintf(ctxt->output, "\tls [path]    list contents of path or the current directory\n");
2903
0
      fprintf(ctxt->output, "\tset xml_fragment replace the current node content with the fragment parsed in context\n");
2904
0
#ifdef LIBXML_XPATH_ENABLED
2905
0
      fprintf(ctxt->output, "\txpath expr   evaluate the XPath expression in that context and print the result\n");
2906
0
      fprintf(ctxt->output, "\tsetns nsreg  register a namespace to a prefix in the XPath evaluation context\n");
2907
0
      fprintf(ctxt->output, "\t             format for nsreg is: prefix=[nsuri] (i.e. prefix= unsets a prefix)\n");
2908
0
      fprintf(ctxt->output, "\tsetrootns    register all namespace found on the root element\n");
2909
0
      fprintf(ctxt->output, "\t             the default namespace if any uses 'defaultns' prefix\n");
2910
0
#endif /* LIBXML_XPATH_ENABLED */
2911
0
      fprintf(ctxt->output, "\tpwd          display current working directory\n");
2912
0
      fprintf(ctxt->output, "\twhereis      display absolute path of [path] or current working directory\n");
2913
0
      fprintf(ctxt->output, "\tquit         leave shell\n");
2914
0
#ifdef LIBXML_OUTPUT_ENABLED
2915
0
      fprintf(ctxt->output, "\tsave [name]  save this document to name or the original name\n");
2916
0
      fprintf(ctxt->output, "\twrite [name] write the current node to the filename\n");
2917
0
#endif /* LIBXML_OUTPUT_ENABLED */
2918
0
#ifdef LIBXML_VALID_ENABLED
2919
0
      fprintf(ctxt->output, "\tvalidate     check the document for errors\n");
2920
0
#endif /* LIBXML_VALID_ENABLED */
2921
0
#ifdef LIBXML_SCHEMAS_ENABLED
2922
0
      fprintf(ctxt->output, "\trelaxng rng  validate the document against the Relax-NG schemas\n");
2923
0
#endif
2924
0
      fprintf(ctxt->output, "\tgrep string  search for a string in the subtree\n");
2925
0
#ifdef LIBXML_VALID_ENABLED
2926
0
        } else if (!strcmp(command, "validate")) {
2927
0
            xmlShellValidate(ctxt, arg, NULL, NULL);
2928
0
#endif /* LIBXML_VALID_ENABLED */
2929
0
        } else if (!strcmp(command, "load")) {
2930
0
            xmlShellLoad(ctxt, arg, NULL, NULL);
2931
0
#ifdef LIBXML_SCHEMAS_ENABLED
2932
0
        } else if (!strcmp(command, "relaxng")) {
2933
0
            xmlShellRNGValidate(ctxt, arg, NULL, NULL);
2934
0
#endif
2935
0
#ifdef LIBXML_OUTPUT_ENABLED
2936
0
        } else if (!strcmp(command, "save")) {
2937
0
            xmlShellSave(ctxt, arg, NULL, NULL);
2938
0
        } else if (!strcmp(command, "write")) {
2939
0
      if (arg[0] == 0)
2940
0
    fprintf(ctxt->output,
2941
0
                        "Write command requires a filename argument\n");
2942
0
      else
2943
0
    xmlShellWrite(ctxt, arg, ctxt->node, NULL);
2944
0
#endif /* LIBXML_OUTPUT_ENABLED */
2945
0
        } else if (!strcmp(command, "grep")) {
2946
0
            xmlShellGrep(ctxt, arg, ctxt->node, NULL);
2947
0
        } else if (!strcmp(command, "pwd")) {
2948
0
            char dir[500];
2949
2950
0
            if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
2951
0
                fprintf(ctxt->output, "%s\n", dir);
2952
0
        } else if (!strcmp(command, "du")) {
2953
0
            if (arg[0] == 0) {
2954
0
                xmlShellDu(ctxt, NULL, ctxt->node, NULL);
2955
0
            } else {
2956
0
                ctxt->pctxt->node = ctxt->node;
2957
0
#ifdef LIBXML_XPATH_ENABLED
2958
0
                ctxt->pctxt->node = ctxt->node;
2959
0
                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2960
#else
2961
                list = NULL;
2962
#endif /* LIBXML_XPATH_ENABLED */
2963
0
                if (list != NULL) {
2964
0
                    switch (list->type) {
2965
0
                        case XPATH_UNDEFINED:
2966
0
                            fprintf(ctxt->output,
2967
0
                                            "%s: no such node\n", arg);
2968
0
                            break;
2969
0
                        case XPATH_NODESET:{
2970
0
                            int indx;
2971
2972
0
                            if (list->nodesetval == NULL)
2973
0
                                break;
2974
2975
0
                            for (indx = 0;
2976
0
                                 indx < list->nodesetval->nodeNr;
2977
0
                                 indx++)
2978
0
                                xmlShellDu(ctxt, NULL,
2979
0
                                           list->nodesetval->
2980
0
                                           nodeTab[indx], NULL);
2981
0
                            break;
2982
0
                        }
2983
0
                        case XPATH_BOOLEAN:
2984
0
                            fprintf(ctxt->output,
2985
0
                                            "%s is a Boolean\n", arg);
2986
0
                            break;
2987
0
                        case XPATH_NUMBER:
2988
0
                            fprintf(ctxt->output,
2989
0
                                            "%s is a number\n", arg);
2990
0
                            break;
2991
0
                        case XPATH_STRING:
2992
0
                            fprintf(ctxt->output,
2993
0
                                            "%s is a string\n", arg);
2994
0
                            break;
2995
#ifdef LIBXML_XPTR_LOCS_ENABLED
2996
                        case XPATH_POINT:
2997
                            fprintf(ctxt->output,
2998
                                            "%s is a point\n", arg);
2999
                            break;
3000
                        case XPATH_RANGE:
3001
                            fprintf(ctxt->output,
3002
                                            "%s is a range\n", arg);
3003
                            break;
3004
                        case XPATH_LOCATIONSET:
3005
                            fprintf(ctxt->output,
3006
                                            "%s is a range\n", arg);
3007
                            break;
3008
#endif /* LIBXML_XPTR_LOCS_ENABLED */
3009
0
                        case XPATH_USERS:
3010
0
                            fprintf(ctxt->output,
3011
0
                                            "%s is user-defined\n", arg);
3012
0
                            break;
3013
0
                        case XPATH_XSLT_TREE:
3014
0
                            fprintf(ctxt->output,
3015
0
                                            "%s is an XSLT value tree\n",
3016
0
                                            arg);
3017
0
                            break;
3018
0
                    }
3019
0
#ifdef LIBXML_XPATH_ENABLED
3020
0
                    xmlXPathFreeObject(list);
3021
0
#endif
3022
0
                } else {
3023
0
                    fprintf(ctxt->output,
3024
0
                                    "%s: no such node\n", arg);
3025
0
                }
3026
0
                ctxt->pctxt->node = NULL;
3027
0
            }
3028
0
        } else if (!strcmp(command, "base")) {
3029
0
            xmlShellBase(ctxt, NULL, ctxt->node, NULL);
3030
0
        } else if (!strcmp(command, "set")) {
3031
0
      xmlShellSetContent(ctxt, arg, ctxt->node, NULL);
3032
0
#ifdef LIBXML_XPATH_ENABLED
3033
0
        } else if (!strcmp(command, "setns")) {
3034
0
            if (arg[0] == 0) {
3035
0
    fprintf(ctxt->output,
3036
0
        "setns: prefix=[nsuri] required\n");
3037
0
            } else {
3038
0
                xmlShellRegisterNamespace(ctxt, arg, NULL, NULL);
3039
0
            }
3040
0
        } else if (!strcmp(command, "setrootns")) {
3041
0
      xmlNodePtr root;
3042
3043
0
      root = xmlDocGetRootElement(ctxt->doc);
3044
0
      xmlShellRegisterRootNamespaces(ctxt, NULL, root, NULL);
3045
0
        } else if (!strcmp(command, "xpath")) {
3046
0
            if (arg[0] == 0) {
3047
0
    fprintf(ctxt->output,
3048
0
        "xpath: expression required\n");
3049
0
      } else {
3050
0
                ctxt->pctxt->node = ctxt->node;
3051
0
                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
3052
0
    xmlXPathDebugDumpObject(ctxt->output, list, 0);
3053
0
    xmlXPathFreeObject(list);
3054
0
      }
3055
0
#endif /* LIBXML_XPATH_ENABLED */
3056
0
#ifdef LIBXML_TREE_ENABLED
3057
0
        } else if (!strcmp(command, "setbase")) {
3058
0
            xmlShellSetBase(ctxt, arg, ctxt->node, NULL);
3059
0
#endif
3060
0
        } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) {
3061
0
            int dir = (!strcmp(command, "dir"));
3062
3063
0
            if (arg[0] == 0) {
3064
0
                if (dir)
3065
0
                    xmlShellDir(ctxt, NULL, ctxt->node, NULL);
3066
0
                else
3067
0
                    xmlShellList(ctxt, NULL, ctxt->node, NULL);
3068
0
            } else {
3069
0
                ctxt->pctxt->node = ctxt->node;
3070
0
#ifdef LIBXML_XPATH_ENABLED
3071
0
                ctxt->pctxt->node = ctxt->node;
3072
0
                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
3073
#else
3074
                list = NULL;
3075
#endif /* LIBXML_XPATH_ENABLED */
3076
0
                if (list != NULL) {
3077
0
                    switch (list->type) {
3078
0
                        case XPATH_UNDEFINED:
3079
0
                            fprintf(ctxt->output,
3080
0
                                            "%s: no such node\n", arg);
3081
0
                            break;
3082
0
                        case XPATH_NODESET:{
3083
0
                                int indx;
3084
3085
0
        if (list->nodesetval == NULL)
3086
0
            break;
3087
3088
0
                                for (indx = 0;
3089
0
                                     indx < list->nodesetval->nodeNr;
3090
0
                                     indx++) {
3091
0
                                    if (dir)
3092
0
                                        xmlShellDir(ctxt, NULL,
3093
0
                                                    list->nodesetval->
3094
0
                                                    nodeTab[indx], NULL);
3095
0
                                    else
3096
0
                                        xmlShellList(ctxt, NULL,
3097
0
                                                     list->nodesetval->
3098
0
                                                     nodeTab[indx], NULL);
3099
0
                                }
3100
0
                                break;
3101
0
                            }
3102
0
                        case XPATH_BOOLEAN:
3103
0
                            fprintf(ctxt->output,
3104
0
                                            "%s is a Boolean\n", arg);
3105
0
                            break;
3106
0
                        case XPATH_NUMBER:
3107
0
                            fprintf(ctxt->output,
3108
0
                                            "%s is a number\n", arg);
3109
0
                            break;
3110
0
                        case XPATH_STRING:
3111
0
                            fprintf(ctxt->output,
3112
0
                                            "%s is a string\n", arg);
3113
0
                            break;
3114
#ifdef LIBXML_XPTR_LOCS_ENABLED
3115
                        case XPATH_POINT:
3116
                            fprintf(ctxt->output,
3117
                                            "%s is a point\n", arg);
3118
                            break;
3119
                        case XPATH_RANGE:
3120
                            fprintf(ctxt->output,
3121
                                            "%s is a range\n", arg);
3122
                            break;
3123
                        case XPATH_LOCATIONSET:
3124
                            fprintf(ctxt->output,
3125
                                            "%s is a range\n", arg);
3126
                            break;
3127
#endif /* LIBXML_XPTR_LOCS_ENABLED */
3128
0
                        case XPATH_USERS:
3129
0
                            fprintf(ctxt->output,
3130
0
                                            "%s is user-defined\n", arg);
3131
0
                            break;
3132
0
                        case XPATH_XSLT_TREE:
3133
0
                            fprintf(ctxt->output,
3134
0
                                            "%s is an XSLT value tree\n",
3135
0
                                            arg);
3136
0
                            break;
3137
0
                    }
3138
0
#ifdef LIBXML_XPATH_ENABLED
3139
0
                    xmlXPathFreeObject(list);
3140
0
#endif
3141
0
                } else {
3142
0
                    fprintf(ctxt->output,
3143
0
                                    "%s: no such node\n", arg);
3144
0
                }
3145
0
                ctxt->pctxt->node = NULL;
3146
0
            }
3147
0
        } else if (!strcmp(command, "whereis")) {
3148
0
            char dir[500];
3149
3150
0
            if (arg[0] == 0) {
3151
0
                if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
3152
0
                    fprintf(ctxt->output, "%s\n", dir);
3153
0
            } else {
3154
0
                ctxt->pctxt->node = ctxt->node;
3155
0
#ifdef LIBXML_XPATH_ENABLED
3156
0
                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
3157
#else
3158
                list = NULL;
3159
#endif /* LIBXML_XPATH_ENABLED */
3160
0
                if (list != NULL) {
3161
0
                    switch (list->type) {
3162
0
                        case XPATH_UNDEFINED:
3163
0
                            fprintf(ctxt->output,
3164
0
                                            "%s: no such node\n", arg);
3165
0
                            break;
3166
0
                        case XPATH_NODESET:{
3167
0
                                int indx;
3168
3169
0
        if (list->nodesetval == NULL)
3170
0
            break;
3171
3172
0
                                for (indx = 0;
3173
0
                                     indx < list->nodesetval->nodeNr;
3174
0
                                     indx++) {
3175
0
                                    if (!xmlShellPwd(ctxt, dir, list->nodesetval->
3176
0
                                                     nodeTab[indx], NULL))
3177
0
                                        fprintf(ctxt->output, "%s\n", dir);
3178
0
                                }
3179
0
                                break;
3180
0
                            }
3181
0
                        case XPATH_BOOLEAN:
3182
0
                            fprintf(ctxt->output,
3183
0
                                            "%s is a Boolean\n", arg);
3184
0
                            break;
3185
0
                        case XPATH_NUMBER:
3186
0
                            fprintf(ctxt->output,
3187
0
                                            "%s is a number\n", arg);
3188
0
                            break;
3189
0
                        case XPATH_STRING:
3190
0
                            fprintf(ctxt->output,
3191
0
                                            "%s is a string\n", arg);
3192
0
                            break;
3193
#ifdef LIBXML_XPTR_LOCS_ENABLED
3194
                        case XPATH_POINT:
3195
                            fprintf(ctxt->output,
3196
                                            "%s is a point\n", arg);
3197
                            break;
3198
                        case XPATH_RANGE:
3199
                            fprintf(ctxt->output,
3200
                                            "%s is a range\n", arg);
3201
                            break;
3202
                        case XPATH_LOCATIONSET:
3203
                            fprintf(ctxt->output,
3204
                                            "%s is a range\n", arg);
3205
                            break;
3206
#endif /* LIBXML_XPTR_LOCS_ENABLED */
3207
0
                        case XPATH_USERS:
3208
0
                            fprintf(ctxt->output,
3209
0
                                            "%s is user-defined\n", arg);
3210
0
                            break;
3211
0
                        case XPATH_XSLT_TREE:
3212
0
                            fprintf(ctxt->output,
3213
0
                                            "%s is an XSLT value tree\n",
3214
0
                                            arg);
3215
0
                            break;
3216
0
                    }
3217
0
#ifdef LIBXML_XPATH_ENABLED
3218
0
                    xmlXPathFreeObject(list);
3219
0
#endif
3220
0
                } else {
3221
0
                    fprintf(ctxt->output,
3222
0
                                    "%s: no such node\n", arg);
3223
0
                }
3224
0
                ctxt->pctxt->node = NULL;
3225
0
            }
3226
0
        } else if (!strcmp(command, "cd")) {
3227
0
            if (arg[0] == 0) {
3228
0
                ctxt->node = (xmlNodePtr) ctxt->doc;
3229
0
            } else {
3230
0
#ifdef LIBXML_XPATH_ENABLED
3231
0
                int l;
3232
3233
0
                ctxt->pctxt->node = ctxt->node;
3234
0
    l = strlen(arg);
3235
0
    if ((l >= 2) && (arg[l - 1] == '/'))
3236
0
        arg[l - 1] = 0;
3237
0
                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
3238
#else
3239
                list = NULL;
3240
#endif /* LIBXML_XPATH_ENABLED */
3241
0
                if (list != NULL) {
3242
0
                    switch (list->type) {
3243
0
                        case XPATH_UNDEFINED:
3244
0
                            fprintf(ctxt->output,
3245
0
                                            "%s: no such node\n", arg);
3246
0
                            break;
3247
0
                        case XPATH_NODESET:
3248
0
                            if (list->nodesetval != NULL) {
3249
0
        if (list->nodesetval->nodeNr == 1) {
3250
0
            ctxt->node = list->nodesetval->nodeTab[0];
3251
0
            if ((ctxt->node != NULL) &&
3252
0
                (ctxt->node->type ==
3253
0
           XML_NAMESPACE_DECL)) {
3254
0
          fprintf(ctxt->output,
3255
0
                "cannot cd to namespace\n");
3256
0
          ctxt->node = NULL;
3257
0
            }
3258
0
        } else
3259
0
            fprintf(ctxt->output,
3260
0
                "%s is a %d Node Set\n",
3261
0
                arg,
3262
0
                list->nodesetval->nodeNr);
3263
0
                            } else
3264
0
                                fprintf(ctxt->output,
3265
0
                                                "%s is an empty Node Set\n",
3266
0
                                                arg);
3267
0
                            break;
3268
0
                        case XPATH_BOOLEAN:
3269
0
                            fprintf(ctxt->output,
3270
0
                                            "%s is a Boolean\n", arg);
3271
0
                            break;
3272
0
                        case XPATH_NUMBER:
3273
0
                            fprintf(ctxt->output,
3274
0
                                            "%s is a number\n", arg);
3275
0
                            break;
3276
0
                        case XPATH_STRING:
3277
0
                            fprintf(ctxt->output,
3278
0
                                            "%s is a string\n", arg);
3279
0
                            break;
3280
#ifdef LIBXML_XPTR_LOCS_ENABLED
3281
                        case XPATH_POINT:
3282
                            fprintf(ctxt->output,
3283
                                            "%s is a point\n", arg);
3284
                            break;
3285
                        case XPATH_RANGE:
3286
                            fprintf(ctxt->output,
3287
                                            "%s is a range\n", arg);
3288
                            break;
3289
                        case XPATH_LOCATIONSET:
3290
                            fprintf(ctxt->output,
3291
                                            "%s is a range\n", arg);
3292
                            break;
3293
#endif /* LIBXML_XPTR_LOCS_ENABLED */
3294
0
                        case XPATH_USERS:
3295
0
                            fprintf(ctxt->output,
3296
0
                                            "%s is user-defined\n", arg);
3297
0
                            break;
3298
0
                        case XPATH_XSLT_TREE:
3299
0
                            fprintf(ctxt->output,
3300
0
                                            "%s is an XSLT value tree\n",
3301
0
                                            arg);
3302
0
                            break;
3303
0
                    }
3304
0
#ifdef LIBXML_XPATH_ENABLED
3305
0
                    xmlXPathFreeObject(list);
3306
0
#endif
3307
0
                } else {
3308
0
                    fprintf(ctxt->output,
3309
0
                                    "%s: no such node\n", arg);
3310
0
                }
3311
0
                ctxt->pctxt->node = NULL;
3312
0
            }
3313
0
#ifdef LIBXML_OUTPUT_ENABLED
3314
0
        } else if (!strcmp(command, "cat")) {
3315
0
            if (arg[0] == 0) {
3316
0
                xmlShellCat(ctxt, NULL, ctxt->node, NULL);
3317
0
            } else {
3318
0
                ctxt->pctxt->node = ctxt->node;
3319
0
#ifdef LIBXML_XPATH_ENABLED
3320
0
                ctxt->pctxt->node = ctxt->node;
3321
0
                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
3322
#else
3323
                list = NULL;
3324
#endif /* LIBXML_XPATH_ENABLED */
3325
0
                if (list != NULL) {
3326
0
                    switch (list->type) {
3327
0
                        case XPATH_UNDEFINED:
3328
0
                            fprintf(ctxt->output,
3329
0
                                            "%s: no such node\n", arg);
3330
0
                            break;
3331
0
                        case XPATH_NODESET:{
3332
0
                                int indx;
3333
3334
0
        if (list->nodesetval == NULL)
3335
0
            break;
3336
3337
0
                                for (indx = 0;
3338
0
                                     indx < list->nodesetval->nodeNr;
3339
0
                                     indx++) {
3340
0
                                    if (i > 0)
3341
0
                                        fprintf(ctxt->output, " -------\n");
3342
0
                                    xmlShellCat(ctxt, NULL,
3343
0
                                                list->nodesetval->
3344
0
                                                nodeTab[indx], NULL);
3345
0
                                }
3346
0
                                break;
3347
0
                            }
3348
0
                        case XPATH_BOOLEAN:
3349
0
                            fprintf(ctxt->output,
3350
0
                                            "%s is a Boolean\n", arg);
3351
0
                            break;
3352
0
                        case XPATH_NUMBER:
3353
0
                            fprintf(ctxt->output,
3354
0
                                            "%s is a number\n", arg);
3355
0
                            break;
3356
0
                        case XPATH_STRING:
3357
0
                            fprintf(ctxt->output,
3358
0
                                            "%s is a string\n", arg);
3359
0
                            break;
3360
#ifdef LIBXML_XPTR_LOCS_ENABLED
3361
                        case XPATH_POINT:
3362
                            fprintf(ctxt->output,
3363
                                            "%s is a point\n", arg);
3364
                            break;
3365
                        case XPATH_RANGE:
3366
                            fprintf(ctxt->output,
3367
                                            "%s is a range\n", arg);
3368
                            break;
3369
                        case XPATH_LOCATIONSET:
3370
                            fprintf(ctxt->output,
3371
                                            "%s is a range\n", arg);
3372
                            break;
3373
#endif /* LIBXML_XPTR_LOCS_ENABLED */
3374
0
                        case XPATH_USERS:
3375
0
                            fprintf(ctxt->output,
3376
0
                                            "%s is user-defined\n", arg);
3377
0
                            break;
3378
0
                        case XPATH_XSLT_TREE:
3379
0
                            fprintf(ctxt->output,
3380
0
                                            "%s is an XSLT value tree\n",
3381
0
                                            arg);
3382
0
                            break;
3383
0
                    }
3384
0
#ifdef LIBXML_XPATH_ENABLED
3385
0
                    xmlXPathFreeObject(list);
3386
0
#endif
3387
0
                } else {
3388
0
                    fprintf(ctxt->output,
3389
0
                                    "%s: no such node\n", arg);
3390
0
                }
3391
0
                ctxt->pctxt->node = NULL;
3392
0
            }
3393
0
#endif /* LIBXML_OUTPUT_ENABLED */
3394
0
        } else {
3395
0
            fprintf(ctxt->output,
3396
0
                            "Unknown command %s\n", command);
3397
0
        }
3398
0
        free(cmdline);          /* not xmlFree here ! */
3399
0
  cmdline = NULL;
3400
0
    }
3401
0
#ifdef LIBXML_XPATH_ENABLED
3402
0
    xmlXPathFreeContext(ctxt->pctxt);
3403
0
#endif /* LIBXML_XPATH_ENABLED */
3404
0
    if (ctxt->loaded) {
3405
0
        xmlFreeDoc(ctxt->doc);
3406
0
    }
3407
0
    if (ctxt->filename != NULL)
3408
0
        xmlFree(ctxt->filename);
3409
0
    xmlFree(ctxt);
3410
0
    if (cmdline != NULL)
3411
0
        free(cmdline);          /* not xmlFree here ! */
3412
0
}
3413
3414
#endif /* LIBXML_XPATH_ENABLED */
3415
3416
#endif /* LIBXML_DEBUG_ENABLED */