Coverage Report

Created: 2023-06-07 06:06

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