Coverage Report

Created: 2025-08-04 07:15

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