Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/xml2/debugXML.c
4393 views
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 <[email protected]>
8
*/
9
10
#define IN_LIBXML
11
#include "libxml.h"
12
#ifdef LIBXML_DEBUG_ENABLED
13
14
#include <string.h>
15
#include <stdlib.h>
16
17
#include <libxml/xmlmemory.h>
18
#include <libxml/tree.h>
19
#include <libxml/parser.h>
20
#include <libxml/parserInternals.h>
21
#include <libxml/debugXML.h>
22
#include <libxml/HTMLtree.h>
23
#include <libxml/HTMLparser.h>
24
#include <libxml/xmlerror.h>
25
#include <libxml/xpathInternals.h>
26
#include <libxml/uri.h>
27
#ifdef LIBXML_SCHEMAS_ENABLED
28
#include <libxml/relaxng.h>
29
#endif
30
31
#include "private/error.h"
32
33
#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
{
55
int i;
56
57
ctxt->depth = 0;
58
ctxt->check = 0;
59
ctxt->errors = 0;
60
ctxt->output = stdout;
61
ctxt->doc = NULL;
62
ctxt->node = NULL;
63
ctxt->dict = NULL;
64
ctxt->nodict = 0;
65
ctxt->options = 0;
66
for (i = 0; i < 100; i++)
67
ctxt->shift[i] = ' ';
68
ctxt->shift[100] = 0;
69
}
70
71
static void
72
xmlCtxtDumpCleanCtxt(xmlDebugCtxtPtr ctxt ATTRIBUTE_UNUSED)
73
{
74
/* remove the ATTRIBUTE_UNUSED when this is added */
75
}
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
{
91
xmlNsPtr cur;
92
93
if ((node == NULL) || (ns == NULL))
94
return(-1);
95
96
if ((node->type != XML_ELEMENT_NODE) &&
97
(node->type != XML_ATTRIBUTE_NODE) &&
98
(node->type != XML_DOCUMENT_NODE) &&
99
(node->type != XML_TEXT_NODE) &&
100
(node->type != XML_HTML_DOCUMENT_NODE) &&
101
(node->type != XML_XINCLUDE_START))
102
return(-2);
103
104
while ((node != NULL) &&
105
((node->type == XML_ELEMENT_NODE) ||
106
(node->type == XML_ATTRIBUTE_NODE) ||
107
(node->type == XML_TEXT_NODE) ||
108
(node->type == XML_XINCLUDE_START))) {
109
if ((node->type == XML_ELEMENT_NODE) ||
110
(node->type == XML_XINCLUDE_START)) {
111
cur = node->nsDef;
112
while (cur != NULL) {
113
if (cur == ns)
114
return(1);
115
if (xmlStrEqual(cur->prefix, ns->prefix))
116
return(-2);
117
cur = cur->next;
118
}
119
}
120
node = node->parent;
121
}
122
/* the xml namespace may be declared on the document node */
123
if ((node != NULL) &&
124
((node->type == XML_DOCUMENT_NODE) ||
125
(node->type == XML_HTML_DOCUMENT_NODE))) {
126
xmlNsPtr oldNs = ((xmlDocPtr) node)->oldNs;
127
if (oldNs == ns)
128
return(1);
129
}
130
return(-3);
131
}
132
133
static void
134
xmlCtxtDumpSpaces(xmlDebugCtxtPtr ctxt)
135
{
136
if (ctxt->check)
137
return;
138
if ((ctxt->output != NULL) && (ctxt->depth > 0)) {
139
if (ctxt->depth < 50)
140
fprintf(ctxt->output, "%s", &ctxt->shift[100 - 2 * ctxt->depth]);
141
else
142
fprintf(ctxt->output, "%s", ctxt->shift);
143
}
144
}
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
{
156
ctxt->errors++;
157
__xmlRaiseError(NULL, NULL, NULL,
158
NULL, ctxt->node, XML_FROM_CHECK,
159
error, XML_ERR_ERROR, NULL, 0,
160
NULL, NULL, NULL, 0, 0,
161
"%s", msg);
162
}
163
static void LIBXML_ATTR_FORMAT(3,0)
164
xmlDebugErr2(xmlDebugCtxtPtr ctxt, int error, const char *msg, int extra)
165
{
166
ctxt->errors++;
167
__xmlRaiseError(NULL, NULL, NULL,
168
NULL, ctxt->node, XML_FROM_CHECK,
169
error, XML_ERR_ERROR, NULL, 0,
170
NULL, NULL, NULL, 0, 0,
171
msg, extra);
172
}
173
static void LIBXML_ATTR_FORMAT(3,0)
174
xmlDebugErr3(xmlDebugCtxtPtr ctxt, int error, const char *msg, const char *extra)
175
{
176
ctxt->errors++;
177
__xmlRaiseError(NULL, NULL, NULL,
178
NULL, ctxt->node, XML_FROM_CHECK,
179
error, XML_ERR_ERROR, NULL, 0,
180
NULL, NULL, NULL, 0, 0,
181
msg, extra);
182
}
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
{
195
int ret;
196
197
ret = xmlNsCheckScope(node, ns);
198
if (ret == -2) {
199
if (ns->prefix == NULL)
200
xmlDebugErr(ctxt, XML_CHECK_NS_SCOPE,
201
"Reference to default namespace not in scope\n");
202
else
203
xmlDebugErr3(ctxt, XML_CHECK_NS_SCOPE,
204
"Reference to namespace '%s' not in scope\n",
205
(char *) ns->prefix);
206
}
207
if (ret == -3) {
208
if (ns->prefix == NULL)
209
xmlDebugErr(ctxt, XML_CHECK_NS_ANCESTOR,
210
"Reference to default namespace not on ancestor\n");
211
else
212
xmlDebugErr3(ctxt, XML_CHECK_NS_ANCESTOR,
213
"Reference to namespace '%s' not on ancestor\n",
214
(char *) ns->prefix);
215
}
216
}
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
{
228
if (str == NULL) return;
229
if (ctxt->check) {
230
if (!xmlCheckUTF8(str)) {
231
xmlDebugErr3(ctxt, XML_CHECK_NOT_UTF8,
232
"String is not UTF-8 %s", (const char *) str);
233
}
234
}
235
}
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
{
248
if (ctxt->check) {
249
if (name == NULL) {
250
xmlDebugErr(ctxt, XML_CHECK_NO_NAME, "Name is NULL");
251
return;
252
}
253
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
254
if (xmlValidateName(name, 0)) {
255
xmlDebugErr3(ctxt, XML_CHECK_NOT_NCNAME,
256
"Name is not an NCName '%s'", (const char *) name);
257
}
258
#endif
259
if ((ctxt->dict != NULL) &&
260
(!xmlDictOwns(ctxt->dict, name)) &&
261
((ctxt->doc == NULL) ||
262
((ctxt->doc->parseFlags & (XML_PARSE_SAX1 | XML_PARSE_NODICT)) == 0))) {
263
xmlDebugErr3(ctxt, XML_CHECK_OUTSIDE_DICT,
264
"Name is not from the document dictionary '%s'",
265
(const char *) name);
266
}
267
}
268
}
269
270
static void
271
xmlCtxtGenericNodeCheck(xmlDebugCtxtPtr ctxt, xmlNodePtr node) {
272
xmlDocPtr doc;
273
xmlDictPtr dict;
274
275
doc = node->doc;
276
277
if (node->parent == NULL)
278
xmlDebugErr(ctxt, XML_CHECK_NO_PARENT,
279
"Node has no parent\n");
280
if (node->doc == NULL) {
281
xmlDebugErr(ctxt, XML_CHECK_NO_DOC,
282
"Node has no doc\n");
283
dict = NULL;
284
} else {
285
dict = doc->dict;
286
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
ctxt->nodict = 1;
294
}
295
if (ctxt->doc == NULL)
296
ctxt->doc = doc;
297
298
if (ctxt->dict == NULL) {
299
ctxt->dict = dict;
300
}
301
}
302
if ((node->parent != NULL) && (node->doc != node->parent->doc) &&
303
(!xmlStrEqual(node->name, BAD_CAST "pseudoroot")))
304
xmlDebugErr(ctxt, XML_CHECK_WRONG_DOC,
305
"Node doc differs from parent's one\n");
306
if (node->prev == NULL) {
307
if (node->type == XML_ATTRIBUTE_NODE) {
308
if ((node->parent != NULL) &&
309
(node != (xmlNodePtr) node->parent->properties))
310
xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
311
"Attr has no prev and not first of attr list\n");
312
313
} else if ((node->parent != NULL) && (node->parent->children != node))
314
xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
315
"Node has no prev and not first of parent list\n");
316
} else {
317
if (node->prev->next != node)
318
xmlDebugErr(ctxt, XML_CHECK_WRONG_PREV,
319
"Node prev->next : back link wrong\n");
320
}
321
if (node->next == NULL) {
322
if ((node->parent != NULL) && (node->type != XML_ATTRIBUTE_NODE) &&
323
(node->parent->last != node) &&
324
(node->parent->type == XML_ELEMENT_NODE))
325
xmlDebugErr(ctxt, XML_CHECK_NO_NEXT,
326
"Node has no next and not last of parent list\n");
327
} else {
328
if (node->next->prev != node)
329
xmlDebugErr(ctxt, XML_CHECK_WRONG_NEXT,
330
"Node next->prev : forward link wrong\n");
331
if (node->next->parent != node->parent)
332
xmlDebugErr(ctxt, XML_CHECK_WRONG_PARENT,
333
"Node next->prev : forward link wrong\n");
334
}
335
if (node->type == XML_ELEMENT_NODE) {
336
xmlNsPtr ns;
337
338
ns = node->nsDef;
339
while (ns != NULL) {
340
xmlCtxtNsCheckScope(ctxt, node, ns);
341
ns = ns->next;
342
}
343
if (node->ns != NULL)
344
xmlCtxtNsCheckScope(ctxt, node, node->ns);
345
} else if (node->type == XML_ATTRIBUTE_NODE) {
346
if (node->ns != NULL)
347
xmlCtxtNsCheckScope(ctxt, node, node->ns);
348
}
349
350
if ((node->type != XML_ELEMENT_NODE) &&
351
(node->type != XML_ATTRIBUTE_NODE) &&
352
(node->type != XML_ELEMENT_DECL) &&
353
(node->type != XML_ATTRIBUTE_DECL) &&
354
(node->type != XML_DTD_NODE) &&
355
(node->type != XML_HTML_DOCUMENT_NODE) &&
356
(node->type != XML_DOCUMENT_NODE)) {
357
if (node->content != NULL)
358
xmlCtxtCheckString(ctxt, (const xmlChar *) node->content);
359
}
360
switch (node->type) {
361
case XML_ELEMENT_NODE:
362
case XML_ATTRIBUTE_NODE:
363
xmlCtxtCheckName(ctxt, node->name);
364
break;
365
case XML_TEXT_NODE:
366
if ((node->name == xmlStringText) ||
367
(node->name == xmlStringTextNoenc))
368
break;
369
/* some case of entity substitution can lead to this */
370
if ((ctxt->dict != NULL) &&
371
(node->name == xmlDictLookup(ctxt->dict, BAD_CAST "nbktext",
372
7)))
373
break;
374
375
xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME,
376
"Text node has wrong name '%s'",
377
(const char *) node->name);
378
break;
379
case XML_COMMENT_NODE:
380
if (node->name == xmlStringComment)
381
break;
382
xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME,
383
"Comment node has wrong name '%s'",
384
(const char *) node->name);
385
break;
386
case XML_PI_NODE:
387
xmlCtxtCheckName(ctxt, node->name);
388
break;
389
case XML_CDATA_SECTION_NODE:
390
if (node->name == NULL)
391
break;
392
xmlDebugErr3(ctxt, XML_CHECK_NAME_NOT_NULL,
393
"CData section has non NULL name '%s'",
394
(const char *) node->name);
395
break;
396
case XML_ENTITY_REF_NODE:
397
case XML_ENTITY_NODE:
398
case XML_DOCUMENT_TYPE_NODE:
399
case XML_DOCUMENT_FRAG_NODE:
400
case XML_NOTATION_NODE:
401
case XML_DTD_NODE:
402
case XML_ELEMENT_DECL:
403
case XML_ATTRIBUTE_DECL:
404
case XML_ENTITY_DECL:
405
case XML_NAMESPACE_DECL:
406
case XML_XINCLUDE_START:
407
case XML_XINCLUDE_END:
408
case XML_DOCUMENT_NODE:
409
case XML_HTML_DOCUMENT_NODE:
410
break;
411
}
412
}
413
414
static void
415
xmlCtxtDumpString(xmlDebugCtxtPtr ctxt, const xmlChar * str)
416
{
417
int i;
418
419
if (ctxt->check) {
420
return;
421
}
422
/* TODO: check UTF8 content of the string */
423
if (str == NULL) {
424
fprintf(ctxt->output, "(NULL)");
425
return;
426
}
427
for (i = 0; i < 40; i++)
428
if (str[i] == 0)
429
return;
430
else if (IS_BLANK_CH(str[i]))
431
fputc(' ', ctxt->output);
432
else if (str[i] >= 0x80)
433
fprintf(ctxt->output, "#%X", str[i]);
434
else
435
fputc(str[i], ctxt->output);
436
fprintf(ctxt->output, "...");
437
}
438
439
static void
440
xmlCtxtDumpDtdNode(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd)
441
{
442
xmlCtxtDumpSpaces(ctxt);
443
444
if (dtd == NULL) {
445
if (!ctxt->check)
446
fprintf(ctxt->output, "DTD node is NULL\n");
447
return;
448
}
449
450
if (dtd->type != XML_DTD_NODE) {
451
xmlDebugErr(ctxt, XML_CHECK_NOT_DTD,
452
"Node is not a DTD");
453
return;
454
}
455
if (!ctxt->check) {
456
if (dtd->name != NULL)
457
fprintf(ctxt->output, "DTD(%s)", (char *) dtd->name);
458
else
459
fprintf(ctxt->output, "DTD");
460
if (dtd->ExternalID != NULL)
461
fprintf(ctxt->output, ", PUBLIC %s", (char *) dtd->ExternalID);
462
if (dtd->SystemID != NULL)
463
fprintf(ctxt->output, ", SYSTEM %s", (char *) dtd->SystemID);
464
fprintf(ctxt->output, "\n");
465
}
466
/*
467
* Do a bit of checking
468
*/
469
xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) dtd);
470
}
471
472
static void
473
xmlCtxtDumpAttrDecl(xmlDebugCtxtPtr ctxt, xmlAttributePtr attr)
474
{
475
xmlCtxtDumpSpaces(ctxt);
476
477
if (attr == NULL) {
478
if (!ctxt->check)
479
fprintf(ctxt->output, "Attribute declaration is NULL\n");
480
return;
481
}
482
if (attr->type != XML_ATTRIBUTE_DECL) {
483
xmlDebugErr(ctxt, XML_CHECK_NOT_ATTR_DECL,
484
"Node is not an attribute declaration");
485
return;
486
}
487
if (attr->name != NULL) {
488
if (!ctxt->check)
489
fprintf(ctxt->output, "ATTRDECL(%s)", (char *) attr->name);
490
} else
491
xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
492
"Node attribute declaration has no name");
493
if (attr->elem != NULL) {
494
if (!ctxt->check)
495
fprintf(ctxt->output, " for %s", (char *) attr->elem);
496
} else
497
xmlDebugErr(ctxt, XML_CHECK_NO_ELEM,
498
"Node attribute declaration has no element name");
499
if (!ctxt->check) {
500
switch (attr->atype) {
501
case XML_ATTRIBUTE_CDATA:
502
fprintf(ctxt->output, " CDATA");
503
break;
504
case XML_ATTRIBUTE_ID:
505
fprintf(ctxt->output, " ID");
506
break;
507
case XML_ATTRIBUTE_IDREF:
508
fprintf(ctxt->output, " IDREF");
509
break;
510
case XML_ATTRIBUTE_IDREFS:
511
fprintf(ctxt->output, " IDREFS");
512
break;
513
case XML_ATTRIBUTE_ENTITY:
514
fprintf(ctxt->output, " ENTITY");
515
break;
516
case XML_ATTRIBUTE_ENTITIES:
517
fprintf(ctxt->output, " ENTITIES");
518
break;
519
case XML_ATTRIBUTE_NMTOKEN:
520
fprintf(ctxt->output, " NMTOKEN");
521
break;
522
case XML_ATTRIBUTE_NMTOKENS:
523
fprintf(ctxt->output, " NMTOKENS");
524
break;
525
case XML_ATTRIBUTE_ENUMERATION:
526
fprintf(ctxt->output, " ENUMERATION");
527
break;
528
case XML_ATTRIBUTE_NOTATION:
529
fprintf(ctxt->output, " NOTATION ");
530
break;
531
}
532
if (attr->tree != NULL) {
533
int indx;
534
xmlEnumerationPtr cur = attr->tree;
535
536
for (indx = 0; indx < 5; indx++) {
537
if (indx != 0)
538
fprintf(ctxt->output, "|%s", (char *) cur->name);
539
else
540
fprintf(ctxt->output, " (%s", (char *) cur->name);
541
cur = cur->next;
542
if (cur == NULL)
543
break;
544
}
545
if (cur == NULL)
546
fprintf(ctxt->output, ")");
547
else
548
fprintf(ctxt->output, "...)");
549
}
550
switch (attr->def) {
551
case XML_ATTRIBUTE_NONE:
552
break;
553
case XML_ATTRIBUTE_REQUIRED:
554
fprintf(ctxt->output, " REQUIRED");
555
break;
556
case XML_ATTRIBUTE_IMPLIED:
557
fprintf(ctxt->output, " IMPLIED");
558
break;
559
case XML_ATTRIBUTE_FIXED:
560
fprintf(ctxt->output, " FIXED");
561
break;
562
}
563
if (attr->defaultValue != NULL) {
564
fprintf(ctxt->output, "\"");
565
xmlCtxtDumpString(ctxt, attr->defaultValue);
566
fprintf(ctxt->output, "\"");
567
}
568
fprintf(ctxt->output, "\n");
569
}
570
571
/*
572
* Do a bit of checking
573
*/
574
xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr);
575
}
576
577
static void
578
xmlCtxtDumpElemDecl(xmlDebugCtxtPtr ctxt, xmlElementPtr elem)
579
{
580
xmlCtxtDumpSpaces(ctxt);
581
582
if (elem == NULL) {
583
if (!ctxt->check)
584
fprintf(ctxt->output, "Element declaration is NULL\n");
585
return;
586
}
587
if (elem->type != XML_ELEMENT_DECL) {
588
xmlDebugErr(ctxt, XML_CHECK_NOT_ELEM_DECL,
589
"Node is not an element declaration");
590
return;
591
}
592
if (elem->name != NULL) {
593
if (!ctxt->check) {
594
fprintf(ctxt->output, "ELEMDECL(");
595
xmlCtxtDumpString(ctxt, elem->name);
596
fprintf(ctxt->output, ")");
597
}
598
} else
599
xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
600
"Element declaration has no name");
601
if (!ctxt->check) {
602
switch (elem->etype) {
603
case XML_ELEMENT_TYPE_UNDEFINED:
604
fprintf(ctxt->output, ", UNDEFINED");
605
break;
606
case XML_ELEMENT_TYPE_EMPTY:
607
fprintf(ctxt->output, ", EMPTY");
608
break;
609
case XML_ELEMENT_TYPE_ANY:
610
fprintf(ctxt->output, ", ANY");
611
break;
612
case XML_ELEMENT_TYPE_MIXED:
613
fprintf(ctxt->output, ", MIXED ");
614
break;
615
case XML_ELEMENT_TYPE_ELEMENT:
616
fprintf(ctxt->output, ", MIXED ");
617
break;
618
}
619
if ((elem->type != XML_ELEMENT_NODE) && (elem->content != NULL)) {
620
char buf[5001];
621
622
buf[0] = 0;
623
xmlSnprintfElementContent(buf, 5000, elem->content, 1);
624
buf[5000] = 0;
625
fprintf(ctxt->output, "%s", buf);
626
}
627
fprintf(ctxt->output, "\n");
628
}
629
630
/*
631
* Do a bit of checking
632
*/
633
xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) elem);
634
}
635
636
static void
637
xmlCtxtDumpEntityDecl(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent)
638
{
639
xmlCtxtDumpSpaces(ctxt);
640
641
if (ent == NULL) {
642
if (!ctxt->check)
643
fprintf(ctxt->output, "Entity declaration is NULL\n");
644
return;
645
}
646
if (ent->type != XML_ENTITY_DECL) {
647
xmlDebugErr(ctxt, XML_CHECK_NOT_ENTITY_DECL,
648
"Node is not an entity declaration");
649
return;
650
}
651
if (ent->name != NULL) {
652
if (!ctxt->check) {
653
fprintf(ctxt->output, "ENTITYDECL(");
654
xmlCtxtDumpString(ctxt, ent->name);
655
fprintf(ctxt->output, ")");
656
}
657
} else
658
xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
659
"Entity declaration has no name");
660
if (!ctxt->check) {
661
switch (ent->etype) {
662
case XML_INTERNAL_GENERAL_ENTITY:
663
fprintf(ctxt->output, ", internal\n");
664
break;
665
case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
666
fprintf(ctxt->output, ", external parsed\n");
667
break;
668
case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
669
fprintf(ctxt->output, ", unparsed\n");
670
break;
671
case XML_INTERNAL_PARAMETER_ENTITY:
672
fprintf(ctxt->output, ", parameter\n");
673
break;
674
case XML_EXTERNAL_PARAMETER_ENTITY:
675
fprintf(ctxt->output, ", external parameter\n");
676
break;
677
case XML_INTERNAL_PREDEFINED_ENTITY:
678
fprintf(ctxt->output, ", predefined\n");
679
break;
680
}
681
if (ent->ExternalID) {
682
xmlCtxtDumpSpaces(ctxt);
683
fprintf(ctxt->output, " ExternalID=%s\n",
684
(char *) ent->ExternalID);
685
}
686
if (ent->SystemID) {
687
xmlCtxtDumpSpaces(ctxt);
688
fprintf(ctxt->output, " SystemID=%s\n",
689
(char *) ent->SystemID);
690
}
691
if (ent->URI != NULL) {
692
xmlCtxtDumpSpaces(ctxt);
693
fprintf(ctxt->output, " URI=%s\n", (char *) ent->URI);
694
}
695
if (ent->content) {
696
xmlCtxtDumpSpaces(ctxt);
697
fprintf(ctxt->output, " content=");
698
xmlCtxtDumpString(ctxt, ent->content);
699
fprintf(ctxt->output, "\n");
700
}
701
}
702
703
/*
704
* Do a bit of checking
705
*/
706
xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) ent);
707
}
708
709
static void
710
xmlCtxtDumpNamespace(xmlDebugCtxtPtr ctxt, xmlNsPtr ns)
711
{
712
xmlCtxtDumpSpaces(ctxt);
713
714
if (ns == NULL) {
715
if (!ctxt->check)
716
fprintf(ctxt->output, "namespace node is NULL\n");
717
return;
718
}
719
if (ns->type != XML_NAMESPACE_DECL) {
720
xmlDebugErr(ctxt, XML_CHECK_NOT_NS_DECL,
721
"Node is not a namespace declaration");
722
return;
723
}
724
if (ns->href == NULL) {
725
if (ns->prefix != NULL)
726
xmlDebugErr3(ctxt, XML_CHECK_NO_HREF,
727
"Incomplete namespace %s href=NULL\n",
728
(char *) ns->prefix);
729
else
730
xmlDebugErr(ctxt, XML_CHECK_NO_HREF,
731
"Incomplete default namespace href=NULL\n");
732
} else {
733
if (!ctxt->check) {
734
if (ns->prefix != NULL)
735
fprintf(ctxt->output, "namespace %s href=",
736
(char *) ns->prefix);
737
else
738
fprintf(ctxt->output, "default namespace href=");
739
740
xmlCtxtDumpString(ctxt, ns->href);
741
fprintf(ctxt->output, "\n");
742
}
743
}
744
}
745
746
static void
747
xmlCtxtDumpNamespaceList(xmlDebugCtxtPtr ctxt, xmlNsPtr ns)
748
{
749
while (ns != NULL) {
750
xmlCtxtDumpNamespace(ctxt, ns);
751
ns = ns->next;
752
}
753
}
754
755
static void
756
xmlCtxtDumpEntity(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent)
757
{
758
xmlCtxtDumpSpaces(ctxt);
759
760
if (ent == NULL) {
761
if (!ctxt->check)
762
fprintf(ctxt->output, "Entity is NULL\n");
763
return;
764
}
765
if (!ctxt->check) {
766
switch (ent->etype) {
767
case XML_INTERNAL_GENERAL_ENTITY:
768
fprintf(ctxt->output, "INTERNAL_GENERAL_ENTITY ");
769
break;
770
case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
771
fprintf(ctxt->output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
772
break;
773
case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
774
fprintf(ctxt->output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
775
break;
776
case XML_INTERNAL_PARAMETER_ENTITY:
777
fprintf(ctxt->output, "INTERNAL_PARAMETER_ENTITY ");
778
break;
779
case XML_EXTERNAL_PARAMETER_ENTITY:
780
fprintf(ctxt->output, "EXTERNAL_PARAMETER_ENTITY ");
781
break;
782
default:
783
fprintf(ctxt->output, "ENTITY_%d ! ", (int) ent->etype);
784
}
785
fprintf(ctxt->output, "%s\n", ent->name);
786
if (ent->ExternalID) {
787
xmlCtxtDumpSpaces(ctxt);
788
fprintf(ctxt->output, "ExternalID=%s\n",
789
(char *) ent->ExternalID);
790
}
791
if (ent->SystemID) {
792
xmlCtxtDumpSpaces(ctxt);
793
fprintf(ctxt->output, "SystemID=%s\n", (char *) ent->SystemID);
794
}
795
if (ent->URI) {
796
xmlCtxtDumpSpaces(ctxt);
797
fprintf(ctxt->output, "URI=%s\n", (char *) ent->URI);
798
}
799
if (ent->content) {
800
xmlCtxtDumpSpaces(ctxt);
801
fprintf(ctxt->output, "content=");
802
xmlCtxtDumpString(ctxt, ent->content);
803
fprintf(ctxt->output, "\n");
804
}
805
}
806
}
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
{
819
xmlCtxtDumpSpaces(ctxt);
820
821
if (attr == NULL) {
822
if (!ctxt->check)
823
fprintf(ctxt->output, "Attr is NULL");
824
return;
825
}
826
if (!ctxt->check) {
827
fprintf(ctxt->output, "ATTRIBUTE ");
828
xmlCtxtDumpString(ctxt, attr->name);
829
fprintf(ctxt->output, "\n");
830
if (attr->children != NULL) {
831
ctxt->depth++;
832
xmlCtxtDumpNodeList(ctxt, attr->children);
833
ctxt->depth--;
834
}
835
}
836
if (attr->name == NULL)
837
xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
838
"Attribute has no name");
839
840
/*
841
* Do a bit of checking
842
*/
843
xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr);
844
}
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
{
857
while (attr != NULL) {
858
xmlCtxtDumpAttr(ctxt, attr);
859
attr = attr->next;
860
}
861
}
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
{
874
if (node == NULL) {
875
if (!ctxt->check) {
876
xmlCtxtDumpSpaces(ctxt);
877
fprintf(ctxt->output, "node is NULL\n");
878
}
879
return;
880
}
881
ctxt->node = node;
882
883
switch (node->type) {
884
case XML_ELEMENT_NODE:
885
if (!ctxt->check) {
886
xmlCtxtDumpSpaces(ctxt);
887
fprintf(ctxt->output, "ELEMENT ");
888
if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
889
xmlCtxtDumpString(ctxt, node->ns->prefix);
890
fprintf(ctxt->output, ":");
891
}
892
xmlCtxtDumpString(ctxt, node->name);
893
fprintf(ctxt->output, "\n");
894
}
895
break;
896
case XML_ATTRIBUTE_NODE:
897
if (!ctxt->check)
898
xmlCtxtDumpSpaces(ctxt);
899
fprintf(ctxt->output, "Error, ATTRIBUTE found here\n");
900
xmlCtxtGenericNodeCheck(ctxt, node);
901
return;
902
case XML_TEXT_NODE:
903
if (!ctxt->check) {
904
xmlCtxtDumpSpaces(ctxt);
905
if (node->name == (const xmlChar *) xmlStringTextNoenc)
906
fprintf(ctxt->output, "TEXT no enc");
907
else
908
fprintf(ctxt->output, "TEXT");
909
if (ctxt->options & DUMP_TEXT_TYPE) {
910
if (node->content == (xmlChar *) &(node->properties))
911
fprintf(ctxt->output, " compact\n");
912
else if (xmlDictOwns(ctxt->dict, node->content) == 1)
913
fprintf(ctxt->output, " interned\n");
914
else
915
fprintf(ctxt->output, "\n");
916
} else
917
fprintf(ctxt->output, "\n");
918
}
919
break;
920
case XML_CDATA_SECTION_NODE:
921
if (!ctxt->check) {
922
xmlCtxtDumpSpaces(ctxt);
923
fprintf(ctxt->output, "CDATA_SECTION\n");
924
}
925
break;
926
case XML_ENTITY_REF_NODE:
927
if (!ctxt->check) {
928
xmlCtxtDumpSpaces(ctxt);
929
fprintf(ctxt->output, "ENTITY_REF(%s)\n",
930
(char *) node->name);
931
}
932
break;
933
case XML_ENTITY_NODE:
934
if (!ctxt->check) {
935
xmlCtxtDumpSpaces(ctxt);
936
fprintf(ctxt->output, "ENTITY\n");
937
}
938
break;
939
case XML_PI_NODE:
940
if (!ctxt->check) {
941
xmlCtxtDumpSpaces(ctxt);
942
fprintf(ctxt->output, "PI %s\n", (char *) node->name);
943
}
944
break;
945
case XML_COMMENT_NODE:
946
if (!ctxt->check) {
947
xmlCtxtDumpSpaces(ctxt);
948
fprintf(ctxt->output, "COMMENT\n");
949
}
950
break;
951
case XML_DOCUMENT_NODE:
952
case XML_HTML_DOCUMENT_NODE:
953
if (!ctxt->check) {
954
xmlCtxtDumpSpaces(ctxt);
955
}
956
fprintf(ctxt->output, "Error, DOCUMENT found here\n");
957
xmlCtxtGenericNodeCheck(ctxt, node);
958
return;
959
case XML_DOCUMENT_TYPE_NODE:
960
if (!ctxt->check) {
961
xmlCtxtDumpSpaces(ctxt);
962
fprintf(ctxt->output, "DOCUMENT_TYPE\n");
963
}
964
break;
965
case XML_DOCUMENT_FRAG_NODE:
966
if (!ctxt->check) {
967
xmlCtxtDumpSpaces(ctxt);
968
fprintf(ctxt->output, "DOCUMENT_FRAG\n");
969
}
970
break;
971
case XML_NOTATION_NODE:
972
if (!ctxt->check) {
973
xmlCtxtDumpSpaces(ctxt);
974
fprintf(ctxt->output, "NOTATION\n");
975
}
976
break;
977
case XML_DTD_NODE:
978
xmlCtxtDumpDtdNode(ctxt, (xmlDtdPtr) node);
979
return;
980
case XML_ELEMENT_DECL:
981
xmlCtxtDumpElemDecl(ctxt, (xmlElementPtr) node);
982
return;
983
case XML_ATTRIBUTE_DECL:
984
xmlCtxtDumpAttrDecl(ctxt, (xmlAttributePtr) node);
985
return;
986
case XML_ENTITY_DECL:
987
xmlCtxtDumpEntityDecl(ctxt, (xmlEntityPtr) node);
988
return;
989
case XML_NAMESPACE_DECL:
990
xmlCtxtDumpNamespace(ctxt, (xmlNsPtr) node);
991
return;
992
case XML_XINCLUDE_START:
993
if (!ctxt->check) {
994
xmlCtxtDumpSpaces(ctxt);
995
fprintf(ctxt->output, "INCLUDE START\n");
996
}
997
return;
998
case XML_XINCLUDE_END:
999
if (!ctxt->check) {
1000
xmlCtxtDumpSpaces(ctxt);
1001
fprintf(ctxt->output, "INCLUDE END\n");
1002
}
1003
return;
1004
default:
1005
if (!ctxt->check)
1006
xmlCtxtDumpSpaces(ctxt);
1007
xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE,
1008
"Unknown node type %d\n", node->type);
1009
return;
1010
}
1011
if (node->doc == NULL) {
1012
if (!ctxt->check) {
1013
xmlCtxtDumpSpaces(ctxt);
1014
}
1015
fprintf(ctxt->output, "PBM: doc == NULL !!!\n");
1016
}
1017
ctxt->depth++;
1018
if ((node->type == XML_ELEMENT_NODE) && (node->nsDef != NULL))
1019
xmlCtxtDumpNamespaceList(ctxt, node->nsDef);
1020
if ((node->type == XML_ELEMENT_NODE) && (node->properties != NULL))
1021
xmlCtxtDumpAttrList(ctxt, node->properties);
1022
if (node->type != XML_ENTITY_REF_NODE) {
1023
if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
1024
if (!ctxt->check) {
1025
xmlCtxtDumpSpaces(ctxt);
1026
fprintf(ctxt->output, "content=");
1027
xmlCtxtDumpString(ctxt, node->content);
1028
fprintf(ctxt->output, "\n");
1029
}
1030
}
1031
} else {
1032
xmlEntityPtr ent;
1033
1034
ent = xmlGetDocEntity(node->doc, node->name);
1035
if (ent != NULL)
1036
xmlCtxtDumpEntity(ctxt, ent);
1037
}
1038
ctxt->depth--;
1039
1040
/*
1041
* Do a bit of checking
1042
*/
1043
xmlCtxtGenericNodeCheck(ctxt, node);
1044
}
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
{
1057
if (node == NULL) {
1058
if (!ctxt->check) {
1059
xmlCtxtDumpSpaces(ctxt);
1060
fprintf(ctxt->output, "node is NULL\n");
1061
}
1062
return;
1063
}
1064
xmlCtxtDumpOneNode(ctxt, node);
1065
if ((node->type != XML_NAMESPACE_DECL) &&
1066
(node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
1067
ctxt->depth++;
1068
xmlCtxtDumpNodeList(ctxt, node->children);
1069
ctxt->depth--;
1070
}
1071
}
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
{
1084
while (node != NULL) {
1085
xmlCtxtDumpNode(ctxt, node);
1086
node = node->next;
1087
}
1088
}
1089
1090
static void
1091
xmlCtxtDumpDocHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1092
{
1093
if (doc == NULL) {
1094
if (!ctxt->check)
1095
fprintf(ctxt->output, "DOCUMENT == NULL !\n");
1096
return;
1097
}
1098
ctxt->node = (xmlNodePtr) doc;
1099
1100
switch (doc->type) {
1101
case XML_ELEMENT_NODE:
1102
xmlDebugErr(ctxt, XML_CHECK_FOUND_ELEMENT,
1103
"Misplaced ELEMENT node\n");
1104
break;
1105
case XML_ATTRIBUTE_NODE:
1106
xmlDebugErr(ctxt, XML_CHECK_FOUND_ATTRIBUTE,
1107
"Misplaced ATTRIBUTE node\n");
1108
break;
1109
case XML_TEXT_NODE:
1110
xmlDebugErr(ctxt, XML_CHECK_FOUND_TEXT,
1111
"Misplaced TEXT node\n");
1112
break;
1113
case XML_CDATA_SECTION_NODE:
1114
xmlDebugErr(ctxt, XML_CHECK_FOUND_CDATA,
1115
"Misplaced CDATA node\n");
1116
break;
1117
case XML_ENTITY_REF_NODE:
1118
xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITYREF,
1119
"Misplaced ENTITYREF node\n");
1120
break;
1121
case XML_ENTITY_NODE:
1122
xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITY,
1123
"Misplaced ENTITY node\n");
1124
break;
1125
case XML_PI_NODE:
1126
xmlDebugErr(ctxt, XML_CHECK_FOUND_PI,
1127
"Misplaced PI node\n");
1128
break;
1129
case XML_COMMENT_NODE:
1130
xmlDebugErr(ctxt, XML_CHECK_FOUND_COMMENT,
1131
"Misplaced COMMENT node\n");
1132
break;
1133
case XML_DOCUMENT_NODE:
1134
if (!ctxt->check)
1135
fprintf(ctxt->output, "DOCUMENT\n");
1136
break;
1137
case XML_HTML_DOCUMENT_NODE:
1138
if (!ctxt->check)
1139
fprintf(ctxt->output, "HTML DOCUMENT\n");
1140
break;
1141
case XML_DOCUMENT_TYPE_NODE:
1142
xmlDebugErr(ctxt, XML_CHECK_FOUND_DOCTYPE,
1143
"Misplaced DOCTYPE node\n");
1144
break;
1145
case XML_DOCUMENT_FRAG_NODE:
1146
xmlDebugErr(ctxt, XML_CHECK_FOUND_FRAGMENT,
1147
"Misplaced FRAGMENT node\n");
1148
break;
1149
case XML_NOTATION_NODE:
1150
xmlDebugErr(ctxt, XML_CHECK_FOUND_NOTATION,
1151
"Misplaced NOTATION node\n");
1152
break;
1153
default:
1154
xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE,
1155
"Unknown node type %d\n", doc->type);
1156
}
1157
}
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
{
1169
if (doc == NULL) return;
1170
xmlCtxtDumpDocHead(ctxt, doc);
1171
if (!ctxt->check) {
1172
if (doc->name != NULL) {
1173
fprintf(ctxt->output, "name=");
1174
xmlCtxtDumpString(ctxt, BAD_CAST doc->name);
1175
fprintf(ctxt->output, "\n");
1176
}
1177
if (doc->version != NULL) {
1178
fprintf(ctxt->output, "version=");
1179
xmlCtxtDumpString(ctxt, doc->version);
1180
fprintf(ctxt->output, "\n");
1181
}
1182
if (doc->encoding != NULL) {
1183
fprintf(ctxt->output, "encoding=");
1184
xmlCtxtDumpString(ctxt, doc->encoding);
1185
fprintf(ctxt->output, "\n");
1186
}
1187
if (doc->URL != NULL) {
1188
fprintf(ctxt->output, "URL=");
1189
xmlCtxtDumpString(ctxt, doc->URL);
1190
fprintf(ctxt->output, "\n");
1191
}
1192
if (doc->standalone)
1193
fprintf(ctxt->output, "standalone=true\n");
1194
}
1195
if (doc->oldNs != NULL)
1196
xmlCtxtDumpNamespaceList(ctxt, doc->oldNs);
1197
}
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
{
1209
if (doc == NULL) {
1210
if (!ctxt->check)
1211
fprintf(ctxt->output, "DOCUMENT == NULL !\n");
1212
return;
1213
}
1214
xmlCtxtDumpDocumentHead(ctxt, doc);
1215
if (((doc->type == XML_DOCUMENT_NODE) ||
1216
(doc->type == XML_HTML_DOCUMENT_NODE))
1217
&& (doc->children != NULL)) {
1218
ctxt->depth++;
1219
xmlCtxtDumpNodeList(ctxt, doc->children);
1220
ctxt->depth--;
1221
}
1222
}
1223
1224
static void
1225
xmlCtxtDumpEntityCallback(void *payload, void *data,
1226
const xmlChar *name ATTRIBUTE_UNUSED)
1227
{
1228
xmlEntityPtr cur = (xmlEntityPtr) payload;
1229
xmlDebugCtxtPtr ctxt = (xmlDebugCtxtPtr) data;
1230
if (cur == NULL) {
1231
if (!ctxt->check)
1232
fprintf(ctxt->output, "Entity is NULL");
1233
return;
1234
}
1235
if (!ctxt->check) {
1236
fprintf(ctxt->output, "%s : ", (char *) cur->name);
1237
switch (cur->etype) {
1238
case XML_INTERNAL_GENERAL_ENTITY:
1239
fprintf(ctxt->output, "INTERNAL GENERAL, ");
1240
break;
1241
case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1242
fprintf(ctxt->output, "EXTERNAL PARSED, ");
1243
break;
1244
case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1245
fprintf(ctxt->output, "EXTERNAL UNPARSED, ");
1246
break;
1247
case XML_INTERNAL_PARAMETER_ENTITY:
1248
fprintf(ctxt->output, "INTERNAL PARAMETER, ");
1249
break;
1250
case XML_EXTERNAL_PARAMETER_ENTITY:
1251
fprintf(ctxt->output, "EXTERNAL PARAMETER, ");
1252
break;
1253
default:
1254
xmlDebugErr2(ctxt, XML_CHECK_ENTITY_TYPE,
1255
"Unknown entity type %d\n", cur->etype);
1256
}
1257
if (cur->ExternalID != NULL)
1258
fprintf(ctxt->output, "ID \"%s\"", (char *) cur->ExternalID);
1259
if (cur->SystemID != NULL)
1260
fprintf(ctxt->output, "SYSTEM \"%s\"", (char *) cur->SystemID);
1261
if (cur->orig != NULL)
1262
fprintf(ctxt->output, "\n orig \"%s\"", (char *) cur->orig);
1263
if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL))
1264
fprintf(ctxt->output, "\n content \"%s\"",
1265
(char *) cur->content);
1266
fprintf(ctxt->output, "\n");
1267
}
1268
}
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
{
1280
if (doc == NULL) return;
1281
xmlCtxtDumpDocHead(ctxt, doc);
1282
if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
1283
xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1284
doc->intSubset->entities;
1285
1286
if (!ctxt->check)
1287
fprintf(ctxt->output, "Entities in internal subset\n");
1288
xmlHashScan(table, xmlCtxtDumpEntityCallback, ctxt);
1289
} else
1290
fprintf(ctxt->output, "No entities in internal subset\n");
1291
if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
1292
xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1293
doc->extSubset->entities;
1294
1295
if (!ctxt->check)
1296
fprintf(ctxt->output, "Entities in external subset\n");
1297
xmlHashScan(table, xmlCtxtDumpEntityCallback, ctxt);
1298
} else if (!ctxt->check)
1299
fprintf(ctxt->output, "No entities in external subset\n");
1300
}
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
{
1312
if (dtd == NULL) {
1313
if (!ctxt->check)
1314
fprintf(ctxt->output, "DTD is NULL\n");
1315
return;
1316
}
1317
xmlCtxtDumpDtdNode(ctxt, dtd);
1318
if (dtd->children == NULL)
1319
fprintf(ctxt->output, " DTD is empty\n");
1320
else {
1321
ctxt->depth++;
1322
xmlCtxtDumpNodeList(ctxt, dtd->children);
1323
ctxt->depth--;
1324
}
1325
}
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
{
1343
int i;
1344
1345
if (output == NULL)
1346
output = stdout;
1347
if (str == NULL) {
1348
fprintf(output, "(NULL)");
1349
return;
1350
}
1351
for (i = 0; i < 40; i++)
1352
if (str[i] == 0)
1353
return;
1354
else if (IS_BLANK_CH(str[i]))
1355
fputc(' ', output);
1356
else if (str[i] >= 0x80)
1357
fprintf(output, "#%X", str[i]);
1358
else
1359
fputc(str[i], output);
1360
fprintf(output, "...");
1361
}
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
xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
1373
xmlDebugCtxt ctxt;
1374
1375
if (output == NULL) return;
1376
xmlCtxtDumpInitCtxt(&ctxt);
1377
ctxt.output = output;
1378
ctxt.depth = depth;
1379
xmlCtxtDumpAttr(&ctxt, attr);
1380
xmlCtxtDumpCleanCtxt(&ctxt);
1381
}
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
{
1394
xmlDebugCtxt ctxt;
1395
1396
if (output == NULL) return;
1397
xmlCtxtDumpInitCtxt(&ctxt);
1398
ctxt.output = output;
1399
xmlCtxtDumpEntities(&ctxt, doc);
1400
xmlCtxtDumpCleanCtxt(&ctxt);
1401
}
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
{
1414
xmlDebugCtxt ctxt;
1415
1416
if (output == NULL) return;
1417
xmlCtxtDumpInitCtxt(&ctxt);
1418
ctxt.output = output;
1419
ctxt.depth = depth;
1420
xmlCtxtDumpAttrList(&ctxt, attr);
1421
xmlCtxtDumpCleanCtxt(&ctxt);
1422
}
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
{
1435
xmlDebugCtxt ctxt;
1436
1437
if (output == NULL) return;
1438
xmlCtxtDumpInitCtxt(&ctxt);
1439
ctxt.output = output;
1440
ctxt.depth = depth;
1441
xmlCtxtDumpOneNode(&ctxt, node);
1442
xmlCtxtDumpCleanCtxt(&ctxt);
1443
}
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
{
1456
xmlDebugCtxt ctxt;
1457
1458
if (output == NULL)
1459
output = stdout;
1460
xmlCtxtDumpInitCtxt(&ctxt);
1461
ctxt.output = output;
1462
ctxt.depth = depth;
1463
xmlCtxtDumpNode(&ctxt, node);
1464
xmlCtxtDumpCleanCtxt(&ctxt);
1465
}
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
{
1478
xmlDebugCtxt ctxt;
1479
1480
if (output == NULL)
1481
output = stdout;
1482
xmlCtxtDumpInitCtxt(&ctxt);
1483
ctxt.output = output;
1484
ctxt.depth = depth;
1485
xmlCtxtDumpNodeList(&ctxt, node);
1486
xmlCtxtDumpCleanCtxt(&ctxt);
1487
}
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
{
1499
xmlDebugCtxt ctxt;
1500
1501
if (output == NULL)
1502
output = stdout;
1503
xmlCtxtDumpInitCtxt(&ctxt);
1504
ctxt.options |= DUMP_TEXT_TYPE;
1505
ctxt.output = output;
1506
xmlCtxtDumpDocumentHead(&ctxt, doc);
1507
xmlCtxtDumpCleanCtxt(&ctxt);
1508
}
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
{
1520
xmlDebugCtxt ctxt;
1521
1522
if (output == NULL)
1523
output = stdout;
1524
xmlCtxtDumpInitCtxt(&ctxt);
1525
ctxt.options |= DUMP_TEXT_TYPE;
1526
ctxt.output = output;
1527
xmlCtxtDumpDocument(&ctxt, doc);
1528
xmlCtxtDumpCleanCtxt(&ctxt);
1529
}
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
{
1541
xmlDebugCtxt ctxt;
1542
1543
if (output == NULL)
1544
output = stdout;
1545
xmlCtxtDumpInitCtxt(&ctxt);
1546
ctxt.options |= DUMP_TEXT_TYPE;
1547
ctxt.output = output;
1548
xmlCtxtDumpDTD(&ctxt, dtd);
1549
xmlCtxtDumpCleanCtxt(&ctxt);
1550
}
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
{
1571
xmlDebugCtxt ctxt;
1572
1573
if (output == NULL)
1574
output = stdout;
1575
xmlCtxtDumpInitCtxt(&ctxt);
1576
ctxt.output = output;
1577
ctxt.check = 1;
1578
xmlCtxtDumpDocument(&ctxt, doc);
1579
xmlCtxtDumpCleanCtxt(&ctxt);
1580
return(ctxt.errors);
1581
}
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
xmlLsCountNode(xmlNodePtr node) {
1599
int ret = 0;
1600
xmlNodePtr list = NULL;
1601
1602
if (node == NULL)
1603
return(0);
1604
1605
switch (node->type) {
1606
case XML_ELEMENT_NODE:
1607
list = node->children;
1608
break;
1609
case XML_DOCUMENT_NODE:
1610
case XML_HTML_DOCUMENT_NODE:
1611
list = ((xmlDocPtr) node)->children;
1612
break;
1613
case XML_ATTRIBUTE_NODE:
1614
list = ((xmlAttrPtr) node)->children;
1615
break;
1616
case XML_TEXT_NODE:
1617
case XML_CDATA_SECTION_NODE:
1618
case XML_PI_NODE:
1619
case XML_COMMENT_NODE:
1620
if (node->content != NULL) {
1621
ret = xmlStrlen(node->content);
1622
}
1623
break;
1624
case XML_ENTITY_REF_NODE:
1625
case XML_DOCUMENT_TYPE_NODE:
1626
case XML_ENTITY_NODE:
1627
case XML_DOCUMENT_FRAG_NODE:
1628
case XML_NOTATION_NODE:
1629
case XML_DTD_NODE:
1630
case XML_ELEMENT_DECL:
1631
case XML_ATTRIBUTE_DECL:
1632
case XML_ENTITY_DECL:
1633
case XML_NAMESPACE_DECL:
1634
case XML_XINCLUDE_START:
1635
case XML_XINCLUDE_END:
1636
ret = 1;
1637
break;
1638
}
1639
for (;list != NULL;ret++)
1640
list = list->next;
1641
return(ret);
1642
}
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
xmlLsOneNode(FILE *output, xmlNodePtr node) {
1653
if (output == NULL) return;
1654
if (node == NULL) {
1655
fprintf(output, "NULL\n");
1656
return;
1657
}
1658
switch (node->type) {
1659
case XML_ELEMENT_NODE:
1660
fprintf(output, "-");
1661
break;
1662
case XML_ATTRIBUTE_NODE:
1663
fprintf(output, "a");
1664
break;
1665
case XML_TEXT_NODE:
1666
fprintf(output, "t");
1667
break;
1668
case XML_CDATA_SECTION_NODE:
1669
fprintf(output, "C");
1670
break;
1671
case XML_ENTITY_REF_NODE:
1672
fprintf(output, "e");
1673
break;
1674
case XML_ENTITY_NODE:
1675
fprintf(output, "E");
1676
break;
1677
case XML_PI_NODE:
1678
fprintf(output, "p");
1679
break;
1680
case XML_COMMENT_NODE:
1681
fprintf(output, "c");
1682
break;
1683
case XML_DOCUMENT_NODE:
1684
fprintf(output, "d");
1685
break;
1686
case XML_HTML_DOCUMENT_NODE:
1687
fprintf(output, "h");
1688
break;
1689
case XML_DOCUMENT_TYPE_NODE:
1690
fprintf(output, "T");
1691
break;
1692
case XML_DOCUMENT_FRAG_NODE:
1693
fprintf(output, "F");
1694
break;
1695
case XML_NOTATION_NODE:
1696
fprintf(output, "N");
1697
break;
1698
case XML_NAMESPACE_DECL:
1699
fprintf(output, "n");
1700
break;
1701
default:
1702
fprintf(output, "?");
1703
}
1704
if (node->type != XML_NAMESPACE_DECL) {
1705
if (node->properties != NULL)
1706
fprintf(output, "a");
1707
else
1708
fprintf(output, "-");
1709
if (node->nsDef != NULL)
1710
fprintf(output, "n");
1711
else
1712
fprintf(output, "-");
1713
}
1714
1715
fprintf(output, " %8d ", xmlLsCountNode(node));
1716
1717
switch (node->type) {
1718
case XML_ELEMENT_NODE:
1719
if (node->name != NULL) {
1720
if ((node->ns != NULL) && (node->ns->prefix != NULL))
1721
fprintf(output, "%s:", node->ns->prefix);
1722
fprintf(output, "%s", (const char *) node->name);
1723
}
1724
break;
1725
case XML_ATTRIBUTE_NODE:
1726
if (node->name != NULL)
1727
fprintf(output, "%s", (const char *) node->name);
1728
break;
1729
case XML_TEXT_NODE:
1730
if (node->content != NULL) {
1731
xmlDebugDumpString(output, node->content);
1732
}
1733
break;
1734
case XML_CDATA_SECTION_NODE:
1735
break;
1736
case XML_ENTITY_REF_NODE:
1737
if (node->name != NULL)
1738
fprintf(output, "%s", (const char *) node->name);
1739
break;
1740
case XML_ENTITY_NODE:
1741
if (node->name != NULL)
1742
fprintf(output, "%s", (const char *) node->name);
1743
break;
1744
case XML_PI_NODE:
1745
if (node->name != NULL)
1746
fprintf(output, "%s", (const char *) node->name);
1747
break;
1748
case XML_COMMENT_NODE:
1749
break;
1750
case XML_DOCUMENT_NODE:
1751
break;
1752
case XML_HTML_DOCUMENT_NODE:
1753
break;
1754
case XML_DOCUMENT_TYPE_NODE:
1755
break;
1756
case XML_DOCUMENT_FRAG_NODE:
1757
break;
1758
case XML_NOTATION_NODE:
1759
break;
1760
case XML_NAMESPACE_DECL: {
1761
xmlNsPtr ns = (xmlNsPtr) node;
1762
1763
if (ns->prefix == NULL)
1764
fprintf(output, "default -> %s", (char *)ns->href);
1765
else
1766
fprintf(output, "%s -> %s", (char *)ns->prefix,
1767
(char *)ns->href);
1768
break;
1769
}
1770
default:
1771
if (node->name != NULL)
1772
fprintf(output, "%s", (const char *) node->name);
1773
}
1774
fprintf(output, "\n");
1775
}
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
{
1788
if (boolval)
1789
return("True");
1790
else
1791
return("False");
1792
}
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
{
1820
const char *default_arg = "Result";
1821
1822
if (!arg)
1823
arg = default_arg;
1824
1825
switch (errorType) {
1826
case XPATH_UNDEFINED:
1827
xmlGenericError(xmlGenericErrorContext,
1828
"%s: no such node\n", arg);
1829
break;
1830
1831
case XPATH_BOOLEAN:
1832
xmlGenericError(xmlGenericErrorContext,
1833
"%s is a Boolean\n", arg);
1834
break;
1835
case XPATH_NUMBER:
1836
xmlGenericError(xmlGenericErrorContext,
1837
"%s is a number\n", arg);
1838
break;
1839
case XPATH_STRING:
1840
xmlGenericError(xmlGenericErrorContext,
1841
"%s is a string\n", arg);
1842
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
case XPATH_USERS:
1858
xmlGenericError(xmlGenericErrorContext,
1859
"%s is user-defined\n", arg);
1860
break;
1861
case XPATH_XSLT_TREE:
1862
xmlGenericError(xmlGenericErrorContext,
1863
"%s is an XSLT value tree\n", arg);
1864
break;
1865
}
1866
#if 0
1867
xmlGenericError(xmlGenericErrorContext,
1868
"Try casting the result string function (xpath builtin)\n",
1869
arg);
1870
#endif
1871
}
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
{
1885
FILE *fp;
1886
1887
if (!node)
1888
return;
1889
if (ctxt == NULL)
1890
fp = stdout;
1891
else
1892
fp = ctxt->output;
1893
1894
if (node->type == XML_DOCUMENT_NODE)
1895
xmlDocDump(fp, (xmlDocPtr) node);
1896
else if (node->type == XML_ATTRIBUTE_NODE)
1897
xmlDebugDumpAttrList(fp, (xmlAttrPtr) node, 0);
1898
else
1899
xmlElemDump(fp, node->doc, node);
1900
1901
fprintf(fp, "\n");
1902
}
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
{
1913
xmlShellPrintNodeCtxt(NULL, node);
1914
}
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
{
1927
if (!ctxt)
1928
return;
1929
1930
if (list != NULL) {
1931
switch (list->type) {
1932
case XPATH_NODESET:{
1933
#ifdef LIBXML_OUTPUT_ENABLED
1934
int indx;
1935
1936
if (list->nodesetval) {
1937
for (indx = 0; indx < list->nodesetval->nodeNr;
1938
indx++) {
1939
xmlShellPrintNodeCtxt(ctxt,
1940
list->nodesetval->nodeTab[indx]);
1941
}
1942
} else {
1943
xmlGenericError(xmlGenericErrorContext,
1944
"Empty node set\n");
1945
}
1946
break;
1947
#else
1948
xmlGenericError(xmlGenericErrorContext,
1949
"Node set\n");
1950
#endif /* LIBXML_OUTPUT_ENABLED */
1951
}
1952
case XPATH_BOOLEAN:
1953
xmlGenericError(xmlGenericErrorContext,
1954
"Is a Boolean:%s\n",
1955
xmlBoolToText(list->boolval));
1956
break;
1957
case XPATH_NUMBER:
1958
xmlGenericError(xmlGenericErrorContext,
1959
"Is a number:%0g\n", list->floatval);
1960
break;
1961
case XPATH_STRING:
1962
xmlGenericError(xmlGenericErrorContext,
1963
"Is a string:%s\n", list->stringval);
1964
break;
1965
1966
default:
1967
xmlShellPrintXPathError(list->type, NULL);
1968
}
1969
}
1970
}
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
{
1981
xmlShellPrintXPathResultCtxt(NULL, list);
1982
}
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
{
2001
xmlNodePtr cur;
2002
if (!ctxt)
2003
return (0);
2004
if (node == NULL) {
2005
fprintf(ctxt->output, "NULL\n");
2006
return (0);
2007
}
2008
if ((node->type == XML_DOCUMENT_NODE) ||
2009
(node->type == XML_HTML_DOCUMENT_NODE)) {
2010
cur = ((xmlDocPtr) node)->children;
2011
} else if (node->type == XML_NAMESPACE_DECL) {
2012
xmlLsOneNode(ctxt->output, node);
2013
return (0);
2014
} else if (node->children != NULL) {
2015
cur = node->children;
2016
} else {
2017
xmlLsOneNode(ctxt->output, node);
2018
return (0);
2019
}
2020
while (cur != NULL) {
2021
xmlLsOneNode(ctxt->output, cur);
2022
cur = cur->next;
2023
}
2024
return (0);
2025
}
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
{
2044
xmlChar *base;
2045
if (!ctxt)
2046
return 0;
2047
if (node == NULL) {
2048
fprintf(ctxt->output, "NULL\n");
2049
return (0);
2050
}
2051
2052
base = xmlNodeGetBase(node->doc, node);
2053
2054
if (base == NULL) {
2055
fprintf(ctxt->output, " No base found !!!\n");
2056
} else {
2057
fprintf(ctxt->output, "%s\n", base);
2058
xmlFree(base);
2059
}
2060
return (0);
2061
}
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
{
2081
xmlNodeSetBase(node, (xmlChar*) arg);
2082
return (0);
2083
}
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
{
2104
xmlChar* nsListDup;
2105
xmlChar* prefix;
2106
xmlChar* href;
2107
xmlChar* next;
2108
2109
nsListDup = xmlStrdup((xmlChar *) arg);
2110
next = nsListDup;
2111
while(next != NULL) {
2112
/* skip spaces */
2113
/*while((*next) == ' ') next++;*/
2114
if((*next) == '\0') break;
2115
2116
/* find prefix */
2117
prefix = next;
2118
next = (xmlChar*)xmlStrchr(next, '=');
2119
if(next == NULL) {
2120
fprintf(ctxt->output, "setns: prefix=[nsuri] required\n");
2121
xmlFree(nsListDup);
2122
return(-1);
2123
}
2124
*(next++) = '\0';
2125
2126
/* find href */
2127
href = next;
2128
next = (xmlChar*)xmlStrchr(next, ' ');
2129
if(next != NULL) {
2130
*(next++) = '\0';
2131
}
2132
2133
/* do register namespace */
2134
if(xmlXPathRegisterNs(ctxt->pctxt, prefix, href) != 0) {
2135
fprintf(ctxt->output,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", prefix, href);
2136
xmlFree(nsListDup);
2137
return(-1);
2138
}
2139
}
2140
2141
xmlFree(nsListDup);
2142
return(0);
2143
}
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
{
2160
xmlNsPtr ns;
2161
2162
if ((root == NULL) || (root->type != XML_ELEMENT_NODE) ||
2163
(root->nsDef == NULL) || (ctxt == NULL) || (ctxt->pctxt == NULL))
2164
return(-1);
2165
ns = root->nsDef;
2166
while (ns != NULL) {
2167
if (ns->prefix == NULL)
2168
xmlXPathRegisterNs(ctxt->pctxt, BAD_CAST "defaultns", ns->href);
2169
else
2170
xmlXPathRegisterNs(ctxt->pctxt, ns->prefix, ns->href);
2171
ns = ns->next;
2172
}
2173
return(0);
2174
}
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
{
2193
if (!ctxt)
2194
return (0);
2195
if (node == NULL)
2196
return (0);
2197
if (arg == NULL)
2198
return (0);
2199
#ifdef LIBXML_REGEXP_ENABLED
2200
if ((xmlStrchr((xmlChar *) arg, '?')) ||
2201
(xmlStrchr((xmlChar *) arg, '*')) ||
2202
(xmlStrchr((xmlChar *) arg, '.')) ||
2203
(xmlStrchr((xmlChar *) arg, '['))) {
2204
}
2205
#endif
2206
while (node != NULL) {
2207
if (node->type == XML_COMMENT_NODE) {
2208
if (xmlStrstr(node->content, (xmlChar *) arg)) {
2209
2210
fprintf(ctxt->output, "%s : ", xmlGetNodePath(node));
2211
xmlShellList(ctxt, NULL, node, NULL);
2212
}
2213
} else if (node->type == XML_TEXT_NODE) {
2214
if (xmlStrstr(node->content, (xmlChar *) arg)) {
2215
2216
fprintf(ctxt->output, "%s : ", xmlGetNodePath(node->parent));
2217
xmlShellList(ctxt, NULL, node->parent, NULL);
2218
}
2219
}
2220
2221
/*
2222
* Browse the full subtree, deep first
2223
*/
2224
2225
if ((node->type == XML_DOCUMENT_NODE) ||
2226
(node->type == XML_HTML_DOCUMENT_NODE)) {
2227
node = ((xmlDocPtr) node)->children;
2228
} else if ((node->children != NULL)
2229
&& (node->type != XML_ENTITY_REF_NODE)) {
2230
/* deep first */
2231
node = node->children;
2232
} else if (node->next != NULL) {
2233
/* then siblings */
2234
node = node->next;
2235
} else {
2236
/* go up to parents->next if needed */
2237
while (node != NULL) {
2238
if (node->parent != NULL) {
2239
node = node->parent;
2240
}
2241
if (node->next != NULL) {
2242
node = node->next;
2243
break;
2244
}
2245
if (node->parent == NULL) {
2246
node = NULL;
2247
break;
2248
}
2249
}
2250
}
2251
}
2252
return (0);
2253
}
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
{
2272
if (!ctxt)
2273
return (0);
2274
if (node == NULL) {
2275
fprintf(ctxt->output, "NULL\n");
2276
return (0);
2277
}
2278
if ((node->type == XML_DOCUMENT_NODE) ||
2279
(node->type == XML_HTML_DOCUMENT_NODE)) {
2280
xmlDebugDumpDocumentHead(ctxt->output, (xmlDocPtr) node);
2281
} else if (node->type == XML_ATTRIBUTE_NODE) {
2282
xmlDebugDumpAttr(ctxt->output, (xmlAttrPtr) node, 0);
2283
} else {
2284
xmlDebugDumpOneNode(ctxt->output, node, 0);
2285
}
2286
return (0);
2287
}
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
{
2306
xmlNodePtr results;
2307
xmlParserErrors ret;
2308
2309
if (!ctxt)
2310
return (0);
2311
if (node == NULL) {
2312
fprintf(ctxt->output, "NULL\n");
2313
return (0);
2314
}
2315
if (value == NULL) {
2316
fprintf(ctxt->output, "NULL\n");
2317
return (0);
2318
}
2319
2320
ret = xmlParseInNodeContext(node, value, strlen(value), 0, &results);
2321
if (ret == XML_ERR_OK) {
2322
if (node->children != NULL) {
2323
xmlFreeNodeList(node->children);
2324
node->children = NULL;
2325
node->last = NULL;
2326
}
2327
xmlAddChildList(node, results);
2328
} else {
2329
fprintf(ctxt->output, "failed to parse content\n");
2330
}
2331
return (0);
2332
}
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
{
2352
xmlRelaxNGPtr relaxngschemas;
2353
xmlRelaxNGParserCtxtPtr ctxt;
2354
xmlRelaxNGValidCtxtPtr vctxt;
2355
int ret;
2356
2357
ctxt = xmlRelaxNGNewParserCtxt(schemas);
2358
xmlRelaxNGSetParserErrors(ctxt, xmlGenericError, xmlGenericError, NULL);
2359
relaxngschemas = xmlRelaxNGParse(ctxt);
2360
xmlRelaxNGFreeParserCtxt(ctxt);
2361
if (relaxngschemas == NULL) {
2362
xmlGenericError(xmlGenericErrorContext,
2363
"Relax-NG schema %s failed to compile\n", schemas);
2364
return(-1);
2365
}
2366
vctxt = xmlRelaxNGNewValidCtxt(relaxngschemas);
2367
xmlRelaxNGSetValidErrors(vctxt, xmlGenericError, xmlGenericError, NULL);
2368
ret = xmlRelaxNGValidateDoc(vctxt, sctxt->doc);
2369
if (ret == 0) {
2370
fprintf(stderr, "%s validates\n", sctxt->filename);
2371
} else if (ret > 0) {
2372
fprintf(stderr, "%s fails to validate\n", sctxt->filename);
2373
} else {
2374
fprintf(stderr, "%s validation generated an internal error\n",
2375
sctxt->filename);
2376
}
2377
xmlRelaxNGFreeValidCtxt(vctxt);
2378
if (relaxngschemas != NULL)
2379
xmlRelaxNGFree(relaxngschemas);
2380
return(0);
2381
}
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
{
2401
if (!ctxt)
2402
return (0);
2403
if (node == NULL) {
2404
fprintf(ctxt->output, "NULL\n");
2405
return (0);
2406
}
2407
if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
2408
#ifdef LIBXML_HTML_ENABLED
2409
if (node->type == XML_HTML_DOCUMENT_NODE)
2410
htmlDocDump(ctxt->output, (htmlDocPtr) node);
2411
else
2412
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
} else {
2420
if (node->type == XML_DOCUMENT_NODE)
2421
xmlDocDump(ctxt->output, (xmlDocPtr) node);
2422
else
2423
xmlElemDump(ctxt->output, ctxt->doc, node);
2424
}
2425
fprintf(ctxt->output, "\n");
2426
return (0);
2427
}
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
{
2447
xmlDocPtr doc;
2448
int html = 0;
2449
2450
if ((ctxt == NULL) || (filename == NULL)) return(-1);
2451
if (ctxt->doc != NULL)
2452
html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
2453
2454
if (html) {
2455
#ifdef LIBXML_HTML_ENABLED
2456
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
} else {
2462
doc = xmlReadFile(filename,NULL,0);
2463
}
2464
if (doc != NULL) {
2465
if (ctxt->loaded == 1) {
2466
xmlFreeDoc(ctxt->doc);
2467
}
2468
ctxt->loaded = 1;
2469
#ifdef LIBXML_XPATH_ENABLED
2470
xmlXPathFreeContext(ctxt->pctxt);
2471
#endif /* LIBXML_XPATH_ENABLED */
2472
xmlFree(ctxt->filename);
2473
ctxt->doc = doc;
2474
ctxt->node = (xmlNodePtr) doc;
2475
#ifdef LIBXML_XPATH_ENABLED
2476
ctxt->pctxt = xmlXPathNewContext(doc);
2477
#endif /* LIBXML_XPATH_ENABLED */
2478
ctxt->filename = (char *) xmlCanonicPath((xmlChar *) filename);
2479
} else
2480
return (-1);
2481
return (0);
2482
}
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
{
2502
if (node == NULL)
2503
return (-1);
2504
if ((filename == NULL) || (filename[0] == 0)) {
2505
return (-1);
2506
}
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
switch (node->type) {
2515
case XML_DOCUMENT_NODE:
2516
if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
2517
xmlGenericError(xmlGenericErrorContext,
2518
"Failed to write to %s\n", filename);
2519
return (-1);
2520
}
2521
break;
2522
case XML_HTML_DOCUMENT_NODE:
2523
#ifdef LIBXML_HTML_ENABLED
2524
if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
2525
xmlGenericError(xmlGenericErrorContext,
2526
"Failed to write to %s\n", filename);
2527
return (-1);
2528
}
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
break;
2537
default:{
2538
FILE *f;
2539
2540
f = fopen((char *) filename, "w");
2541
if (f == NULL) {
2542
xmlGenericError(xmlGenericErrorContext,
2543
"Failed to write to %s\n", filename);
2544
return (-1);
2545
}
2546
xmlElemDump(f, ctxt->doc, node);
2547
fclose(f);
2548
}
2549
}
2550
return (0);
2551
}
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
{
2570
if ((ctxt == NULL) || (ctxt->doc == NULL))
2571
return (-1);
2572
if ((filename == NULL) || (filename[0] == 0))
2573
filename = ctxt->filename;
2574
if (filename == NULL)
2575
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
switch (ctxt->doc->type) {
2584
case XML_DOCUMENT_NODE:
2585
if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
2586
xmlGenericError(xmlGenericErrorContext,
2587
"Failed to save to %s\n", filename);
2588
}
2589
break;
2590
case XML_HTML_DOCUMENT_NODE:
2591
#ifdef LIBXML_HTML_ENABLED
2592
if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
2593
xmlGenericError(xmlGenericErrorContext,
2594
"Failed to save to %s\n", filename);
2595
}
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
break;
2603
default:
2604
xmlGenericError(xmlGenericErrorContext,
2605
"To save to subparts of a document use the 'write' command\n");
2606
return (-1);
2607
2608
}
2609
return (0);
2610
}
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
{
2632
xmlValidCtxt vctxt;
2633
int res = -1;
2634
2635
if ((ctxt == NULL) || (ctxt->doc == NULL)) return(-1);
2636
memset(&vctxt, 0, sizeof(vctxt));
2637
vctxt.error = xmlGenericError;
2638
vctxt.warning = xmlGenericError;
2639
2640
if ((dtd == NULL) || (dtd[0] == 0)) {
2641
res = xmlValidateDocument(&vctxt, ctxt->doc);
2642
} else {
2643
xmlDtdPtr subset;
2644
2645
subset = xmlParseDTD(NULL, (xmlChar *) dtd);
2646
if (subset != NULL) {
2647
res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
2648
2649
xmlFreeDtd(subset);
2650
}
2651
}
2652
return (res);
2653
}
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
{
2674
xmlNodePtr node;
2675
int indent = 0, i;
2676
2677
if (!ctxt)
2678
return (-1);
2679
2680
if (tree == NULL)
2681
return (-1);
2682
node = tree;
2683
while (node != NULL) {
2684
if ((node->type == XML_DOCUMENT_NODE) ||
2685
(node->type == XML_HTML_DOCUMENT_NODE)) {
2686
fprintf(ctxt->output, "/\n");
2687
} else if (node->type == XML_ELEMENT_NODE) {
2688
for (i = 0; i < indent; i++)
2689
fprintf(ctxt->output, " ");
2690
if ((node->ns) && (node->ns->prefix))
2691
fprintf(ctxt->output, "%s:", node->ns->prefix);
2692
fprintf(ctxt->output, "%s\n", node->name);
2693
} else {
2694
}
2695
2696
/*
2697
* Browse the full subtree, deep first
2698
*/
2699
2700
if ((node->type == XML_DOCUMENT_NODE) ||
2701
(node->type == XML_HTML_DOCUMENT_NODE)) {
2702
node = ((xmlDocPtr) node)->children;
2703
} else if ((node->children != NULL)
2704
&& (node->type != XML_ENTITY_REF_NODE)) {
2705
/* deep first */
2706
node = node->children;
2707
indent++;
2708
} else if ((node != tree) && (node->next != NULL)) {
2709
/* then siblings */
2710
node = node->next;
2711
} else if (node != tree) {
2712
/* go up to parents->next if needed */
2713
while (node != tree) {
2714
if (node->parent != NULL) {
2715
node = node->parent;
2716
indent--;
2717
}
2718
if ((node != tree) && (node->next != NULL)) {
2719
node = node->next;
2720
break;
2721
}
2722
if (node->parent == NULL) {
2723
node = NULL;
2724
break;
2725
}
2726
if (node == tree) {
2727
node = NULL;
2728
break;
2729
}
2730
}
2731
/* exit condition */
2732
if (node == tree)
2733
node = NULL;
2734
} else
2735
node = NULL;
2736
}
2737
return (0);
2738
}
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
{
2758
xmlChar *path;
2759
2760
if ((node == NULL) || (buffer == NULL))
2761
return (-1);
2762
2763
path = xmlGetNodePath(node);
2764
if (path == NULL)
2765
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
snprintf(buffer, 499, "%s", path);
2776
buffer[499] = '0';
2777
xmlFree(path);
2778
2779
return (0);
2780
}
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
{
2797
char prompt[500] = "/ > ";
2798
char *cmdline = NULL, *cur;
2799
char command[100];
2800
char arg[400];
2801
int i;
2802
xmlShellCtxtPtr ctxt;
2803
xmlXPathObjectPtr list;
2804
2805
if (doc == NULL)
2806
return;
2807
if (filename == NULL)
2808
return;
2809
if (input == NULL)
2810
return;
2811
if (output == NULL)
2812
output = stdout;
2813
ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
2814
if (ctxt == NULL)
2815
return;
2816
ctxt->loaded = 0;
2817
ctxt->doc = doc;
2818
ctxt->input = input;
2819
ctxt->output = output;
2820
ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
2821
ctxt->node = (xmlNodePtr) ctxt->doc;
2822
2823
#ifdef LIBXML_XPATH_ENABLED
2824
ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
2825
if (ctxt->pctxt == NULL) {
2826
xmlFree(ctxt);
2827
return;
2828
}
2829
#endif /* LIBXML_XPATH_ENABLED */
2830
while (1) {
2831
if (ctxt->node == (xmlNodePtr) ctxt->doc)
2832
snprintf(prompt, sizeof(prompt), "%s > ", "/");
2833
else if ((ctxt->node != NULL) && (ctxt->node->name) &&
2834
(ctxt->node->ns) && (ctxt->node->ns->prefix))
2835
snprintf(prompt, sizeof(prompt), "%s:%s > ",
2836
(ctxt->node->ns->prefix), ctxt->node->name);
2837
else if ((ctxt->node != NULL) && (ctxt->node->name))
2838
snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
2839
else
2840
snprintf(prompt, sizeof(prompt), "? > ");
2841
prompt[sizeof(prompt) - 1] = 0;
2842
2843
/*
2844
* Get a new command line
2845
*/
2846
cmdline = ctxt->input(prompt);
2847
if (cmdline == NULL)
2848
break;
2849
2850
/*
2851
* Parse the command itself
2852
*/
2853
cur = cmdline;
2854
while ((*cur == ' ') || (*cur == '\t'))
2855
cur++;
2856
i = 0;
2857
while ((*cur != ' ') && (*cur != '\t') &&
2858
(*cur != '\n') && (*cur != '\r')) {
2859
if (*cur == 0)
2860
break;
2861
command[i++] = *cur++;
2862
}
2863
command[i] = 0;
2864
if (i == 0)
2865
continue;
2866
2867
/*
2868
* Parse the argument
2869
*/
2870
while ((*cur == ' ') || (*cur == '\t'))
2871
cur++;
2872
i = 0;
2873
while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
2874
if (*cur == 0)
2875
break;
2876
arg[i++] = *cur++;
2877
}
2878
arg[i] = 0;
2879
2880
/*
2881
* start interpreting the command
2882
*/
2883
if (!strcmp(command, "exit"))
2884
break;
2885
if (!strcmp(command, "quit"))
2886
break;
2887
if (!strcmp(command, "bye"))
2888
break;
2889
if (!strcmp(command, "help")) {
2890
fprintf(ctxt->output, "\tbase display XML base of the node\n");
2891
fprintf(ctxt->output, "\tsetbase URI change the XML base of the node\n");
2892
fprintf(ctxt->output, "\tbye leave shell\n");
2893
fprintf(ctxt->output, "\tcat [node] display node or current node\n");
2894
fprintf(ctxt->output, "\tcd [path] change directory to path or to root\n");
2895
fprintf(ctxt->output, "\tdir [path] dumps information about the node (namespace, attributes, content)\n");
2896
fprintf(ctxt->output, "\tdu [path] show the structure of the subtree under path or the current node\n");
2897
fprintf(ctxt->output, "\texit leave shell\n");
2898
fprintf(ctxt->output, "\thelp display this help\n");
2899
fprintf(ctxt->output, "\tfree display memory usage\n");
2900
fprintf(ctxt->output, "\tload [name] load a new document with name\n");
2901
fprintf(ctxt->output, "\tls [path] list contents of path or the current directory\n");
2902
fprintf(ctxt->output, "\tset xml_fragment replace the current node content with the fragment parsed in context\n");
2903
#ifdef LIBXML_XPATH_ENABLED
2904
fprintf(ctxt->output, "\txpath expr evaluate the XPath expression in that context and print the result\n");
2905
fprintf(ctxt->output, "\tsetns nsreg register a namespace to a prefix in the XPath evaluation context\n");
2906
fprintf(ctxt->output, "\t format for nsreg is: prefix=[nsuri] (i.e. prefix= unsets a prefix)\n");
2907
fprintf(ctxt->output, "\tsetrootns register all namespace found on the root element\n");
2908
fprintf(ctxt->output, "\t the default namespace if any uses 'defaultns' prefix\n");
2909
#endif /* LIBXML_XPATH_ENABLED */
2910
fprintf(ctxt->output, "\tpwd display current working directory\n");
2911
fprintf(ctxt->output, "\twhereis display absolute path of [path] or current working directory\n");
2912
fprintf(ctxt->output, "\tquit leave shell\n");
2913
#ifdef LIBXML_OUTPUT_ENABLED
2914
fprintf(ctxt->output, "\tsave [name] save this document to name or the original name\n");
2915
fprintf(ctxt->output, "\twrite [name] write the current node to the filename\n");
2916
#endif /* LIBXML_OUTPUT_ENABLED */
2917
#ifdef LIBXML_VALID_ENABLED
2918
fprintf(ctxt->output, "\tvalidate check the document for errors\n");
2919
#endif /* LIBXML_VALID_ENABLED */
2920
#ifdef LIBXML_SCHEMAS_ENABLED
2921
fprintf(ctxt->output, "\trelaxng rng validate the document against the Relax-NG schemas\n");
2922
#endif
2923
fprintf(ctxt->output, "\tgrep string search for a string in the subtree\n");
2924
#ifdef LIBXML_VALID_ENABLED
2925
} else if (!strcmp(command, "validate")) {
2926
xmlShellValidate(ctxt, arg, NULL, NULL);
2927
#endif /* LIBXML_VALID_ENABLED */
2928
} else if (!strcmp(command, "load")) {
2929
xmlShellLoad(ctxt, arg, NULL, NULL);
2930
#ifdef LIBXML_SCHEMAS_ENABLED
2931
} else if (!strcmp(command, "relaxng")) {
2932
xmlShellRNGValidate(ctxt, arg, NULL, NULL);
2933
#endif
2934
#ifdef LIBXML_OUTPUT_ENABLED
2935
} else if (!strcmp(command, "save")) {
2936
xmlShellSave(ctxt, arg, NULL, NULL);
2937
} else if (!strcmp(command, "write")) {
2938
if (arg[0] == 0)
2939
xmlGenericError(xmlGenericErrorContext,
2940
"Write command requires a filename argument\n");
2941
else
2942
xmlShellWrite(ctxt, arg, ctxt->node, NULL);
2943
#endif /* LIBXML_OUTPUT_ENABLED */
2944
} else if (!strcmp(command, "grep")) {
2945
xmlShellGrep(ctxt, arg, ctxt->node, NULL);
2946
} else if (!strcmp(command, "free")) {
2947
if (arg[0] == 0) {
2948
xmlMemShow(ctxt->output, 0);
2949
} else {
2950
int len = 0;
2951
2952
sscanf(arg, "%d", &len);
2953
xmlMemShow(ctxt->output, len);
2954
}
2955
} else if (!strcmp(command, "pwd")) {
2956
char dir[500];
2957
2958
if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
2959
fprintf(ctxt->output, "%s\n", dir);
2960
} else if (!strcmp(command, "du")) {
2961
if (arg[0] == 0) {
2962
xmlShellDu(ctxt, NULL, ctxt->node, NULL);
2963
} else {
2964
ctxt->pctxt->node = ctxt->node;
2965
#ifdef LIBXML_XPATH_ENABLED
2966
ctxt->pctxt->node = ctxt->node;
2967
list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2968
#else
2969
list = NULL;
2970
#endif /* LIBXML_XPATH_ENABLED */
2971
if (list != NULL) {
2972
switch (list->type) {
2973
case XPATH_UNDEFINED:
2974
xmlGenericError(xmlGenericErrorContext,
2975
"%s: no such node\n", arg);
2976
break;
2977
case XPATH_NODESET:{
2978
int indx;
2979
2980
if (list->nodesetval == NULL)
2981
break;
2982
2983
for (indx = 0;
2984
indx < list->nodesetval->nodeNr;
2985
indx++)
2986
xmlShellDu(ctxt, NULL,
2987
list->nodesetval->
2988
nodeTab[indx], NULL);
2989
break;
2990
}
2991
case XPATH_BOOLEAN:
2992
xmlGenericError(xmlGenericErrorContext,
2993
"%s is a Boolean\n", arg);
2994
break;
2995
case XPATH_NUMBER:
2996
xmlGenericError(xmlGenericErrorContext,
2997
"%s is a number\n", arg);
2998
break;
2999
case XPATH_STRING:
3000
xmlGenericError(xmlGenericErrorContext,
3001
"%s is a string\n", arg);
3002
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
case XPATH_USERS:
3018
xmlGenericError(xmlGenericErrorContext,
3019
"%s is user-defined\n", arg);
3020
break;
3021
case XPATH_XSLT_TREE:
3022
xmlGenericError(xmlGenericErrorContext,
3023
"%s is an XSLT value tree\n",
3024
arg);
3025
break;
3026
}
3027
#ifdef LIBXML_XPATH_ENABLED
3028
xmlXPathFreeObject(list);
3029
#endif
3030
} else {
3031
xmlGenericError(xmlGenericErrorContext,
3032
"%s: no such node\n", arg);
3033
}
3034
ctxt->pctxt->node = NULL;
3035
}
3036
} else if (!strcmp(command, "base")) {
3037
xmlShellBase(ctxt, NULL, ctxt->node, NULL);
3038
} else if (!strcmp(command, "set")) {
3039
xmlShellSetContent(ctxt, arg, ctxt->node, NULL);
3040
#ifdef LIBXML_XPATH_ENABLED
3041
} else if (!strcmp(command, "setns")) {
3042
if (arg[0] == 0) {
3043
xmlGenericError(xmlGenericErrorContext,
3044
"setns: prefix=[nsuri] required\n");
3045
} else {
3046
xmlShellRegisterNamespace(ctxt, arg, NULL, NULL);
3047
}
3048
} else if (!strcmp(command, "setrootns")) {
3049
xmlNodePtr root;
3050
3051
root = xmlDocGetRootElement(ctxt->doc);
3052
xmlShellRegisterRootNamespaces(ctxt, NULL, root, NULL);
3053
} else if (!strcmp(command, "xpath")) {
3054
if (arg[0] == 0) {
3055
xmlGenericError(xmlGenericErrorContext,
3056
"xpath: expression required\n");
3057
} else {
3058
ctxt->pctxt->node = ctxt->node;
3059
list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
3060
xmlXPathDebugDumpObject(ctxt->output, list, 0);
3061
xmlXPathFreeObject(list);
3062
}
3063
#endif /* LIBXML_XPATH_ENABLED */
3064
#ifdef LIBXML_TREE_ENABLED
3065
} else if (!strcmp(command, "setbase")) {
3066
xmlShellSetBase(ctxt, arg, ctxt->node, NULL);
3067
#endif
3068
} else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) {
3069
int dir = (!strcmp(command, "dir"));
3070
3071
if (arg[0] == 0) {
3072
if (dir)
3073
xmlShellDir(ctxt, NULL, ctxt->node, NULL);
3074
else
3075
xmlShellList(ctxt, NULL, ctxt->node, NULL);
3076
} else {
3077
ctxt->pctxt->node = ctxt->node;
3078
#ifdef LIBXML_XPATH_ENABLED
3079
ctxt->pctxt->node = ctxt->node;
3080
list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
3081
#else
3082
list = NULL;
3083
#endif /* LIBXML_XPATH_ENABLED */
3084
if (list != NULL) {
3085
switch (list->type) {
3086
case XPATH_UNDEFINED:
3087
xmlGenericError(xmlGenericErrorContext,
3088
"%s: no such node\n", arg);
3089
break;
3090
case XPATH_NODESET:{
3091
int indx;
3092
3093
if (list->nodesetval == NULL)
3094
break;
3095
3096
for (indx = 0;
3097
indx < list->nodesetval->nodeNr;
3098
indx++) {
3099
if (dir)
3100
xmlShellDir(ctxt, NULL,
3101
list->nodesetval->
3102
nodeTab[indx], NULL);
3103
else
3104
xmlShellList(ctxt, NULL,
3105
list->nodesetval->
3106
nodeTab[indx], NULL);
3107
}
3108
break;
3109
}
3110
case XPATH_BOOLEAN:
3111
xmlGenericError(xmlGenericErrorContext,
3112
"%s is a Boolean\n", arg);
3113
break;
3114
case XPATH_NUMBER:
3115
xmlGenericError(xmlGenericErrorContext,
3116
"%s is a number\n", arg);
3117
break;
3118
case XPATH_STRING:
3119
xmlGenericError(xmlGenericErrorContext,
3120
"%s is a string\n", arg);
3121
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
case XPATH_USERS:
3137
xmlGenericError(xmlGenericErrorContext,
3138
"%s is user-defined\n", arg);
3139
break;
3140
case XPATH_XSLT_TREE:
3141
xmlGenericError(xmlGenericErrorContext,
3142
"%s is an XSLT value tree\n",
3143
arg);
3144
break;
3145
}
3146
#ifdef LIBXML_XPATH_ENABLED
3147
xmlXPathFreeObject(list);
3148
#endif
3149
} else {
3150
xmlGenericError(xmlGenericErrorContext,
3151
"%s: no such node\n", arg);
3152
}
3153
ctxt->pctxt->node = NULL;
3154
}
3155
} else if (!strcmp(command, "whereis")) {
3156
char dir[500];
3157
3158
if (arg[0] == 0) {
3159
if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
3160
fprintf(ctxt->output, "%s\n", dir);
3161
} else {
3162
ctxt->pctxt->node = ctxt->node;
3163
#ifdef LIBXML_XPATH_ENABLED
3164
list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
3165
#else
3166
list = NULL;
3167
#endif /* LIBXML_XPATH_ENABLED */
3168
if (list != NULL) {
3169
switch (list->type) {
3170
case XPATH_UNDEFINED:
3171
xmlGenericError(xmlGenericErrorContext,
3172
"%s: no such node\n", arg);
3173
break;
3174
case XPATH_NODESET:{
3175
int indx;
3176
3177
if (list->nodesetval == NULL)
3178
break;
3179
3180
for (indx = 0;
3181
indx < list->nodesetval->nodeNr;
3182
indx++) {
3183
if (!xmlShellPwd(ctxt, dir, list->nodesetval->
3184
nodeTab[indx], NULL))
3185
fprintf(ctxt->output, "%s\n", dir);
3186
}
3187
break;
3188
}
3189
case XPATH_BOOLEAN:
3190
xmlGenericError(xmlGenericErrorContext,
3191
"%s is a Boolean\n", arg);
3192
break;
3193
case XPATH_NUMBER:
3194
xmlGenericError(xmlGenericErrorContext,
3195
"%s is a number\n", arg);
3196
break;
3197
case XPATH_STRING:
3198
xmlGenericError(xmlGenericErrorContext,
3199
"%s is a string\n", arg);
3200
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
case XPATH_USERS:
3216
xmlGenericError(xmlGenericErrorContext,
3217
"%s is user-defined\n", arg);
3218
break;
3219
case XPATH_XSLT_TREE:
3220
xmlGenericError(xmlGenericErrorContext,
3221
"%s is an XSLT value tree\n",
3222
arg);
3223
break;
3224
}
3225
#ifdef LIBXML_XPATH_ENABLED
3226
xmlXPathFreeObject(list);
3227
#endif
3228
} else {
3229
xmlGenericError(xmlGenericErrorContext,
3230
"%s: no such node\n", arg);
3231
}
3232
ctxt->pctxt->node = NULL;
3233
}
3234
} else if (!strcmp(command, "cd")) {
3235
if (arg[0] == 0) {
3236
ctxt->node = (xmlNodePtr) ctxt->doc;
3237
} else {
3238
#ifdef LIBXML_XPATH_ENABLED
3239
int l;
3240
3241
ctxt->pctxt->node = ctxt->node;
3242
l = strlen(arg);
3243
if ((l >= 2) && (arg[l - 1] == '/'))
3244
arg[l - 1] = 0;
3245
list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
3246
#else
3247
list = NULL;
3248
#endif /* LIBXML_XPATH_ENABLED */
3249
if (list != NULL) {
3250
switch (list->type) {
3251
case XPATH_UNDEFINED:
3252
xmlGenericError(xmlGenericErrorContext,
3253
"%s: no such node\n", arg);
3254
break;
3255
case XPATH_NODESET:
3256
if (list->nodesetval != NULL) {
3257
if (list->nodesetval->nodeNr == 1) {
3258
ctxt->node = list->nodesetval->nodeTab[0];
3259
if ((ctxt->node != NULL) &&
3260
(ctxt->node->type ==
3261
XML_NAMESPACE_DECL)) {
3262
xmlGenericError(xmlGenericErrorContext,
3263
"cannot cd to namespace\n");
3264
ctxt->node = NULL;
3265
}
3266
} else
3267
xmlGenericError(xmlGenericErrorContext,
3268
"%s is a %d Node Set\n",
3269
arg,
3270
list->nodesetval->nodeNr);
3271
} else
3272
xmlGenericError(xmlGenericErrorContext,
3273
"%s is an empty Node Set\n",
3274
arg);
3275
break;
3276
case XPATH_BOOLEAN:
3277
xmlGenericError(xmlGenericErrorContext,
3278
"%s is a Boolean\n", arg);
3279
break;
3280
case XPATH_NUMBER:
3281
xmlGenericError(xmlGenericErrorContext,
3282
"%s is a number\n", arg);
3283
break;
3284
case XPATH_STRING:
3285
xmlGenericError(xmlGenericErrorContext,
3286
"%s is a string\n", arg);
3287
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
case XPATH_USERS:
3303
xmlGenericError(xmlGenericErrorContext,
3304
"%s is user-defined\n", arg);
3305
break;
3306
case XPATH_XSLT_TREE:
3307
xmlGenericError(xmlGenericErrorContext,
3308
"%s is an XSLT value tree\n",
3309
arg);
3310
break;
3311
}
3312
#ifdef LIBXML_XPATH_ENABLED
3313
xmlXPathFreeObject(list);
3314
#endif
3315
} else {
3316
xmlGenericError(xmlGenericErrorContext,
3317
"%s: no such node\n", arg);
3318
}
3319
ctxt->pctxt->node = NULL;
3320
}
3321
#ifdef LIBXML_OUTPUT_ENABLED
3322
} else if (!strcmp(command, "cat")) {
3323
if (arg[0] == 0) {
3324
xmlShellCat(ctxt, NULL, ctxt->node, NULL);
3325
} else {
3326
ctxt->pctxt->node = ctxt->node;
3327
#ifdef LIBXML_XPATH_ENABLED
3328
ctxt->pctxt->node = ctxt->node;
3329
list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
3330
#else
3331
list = NULL;
3332
#endif /* LIBXML_XPATH_ENABLED */
3333
if (list != NULL) {
3334
switch (list->type) {
3335
case XPATH_UNDEFINED:
3336
xmlGenericError(xmlGenericErrorContext,
3337
"%s: no such node\n", arg);
3338
break;
3339
case XPATH_NODESET:{
3340
int indx;
3341
3342
if (list->nodesetval == NULL)
3343
break;
3344
3345
for (indx = 0;
3346
indx < list->nodesetval->nodeNr;
3347
indx++) {
3348
if (i > 0)
3349
fprintf(ctxt->output, " -------\n");
3350
xmlShellCat(ctxt, NULL,
3351
list->nodesetval->
3352
nodeTab[indx], NULL);
3353
}
3354
break;
3355
}
3356
case XPATH_BOOLEAN:
3357
xmlGenericError(xmlGenericErrorContext,
3358
"%s is a Boolean\n", arg);
3359
break;
3360
case XPATH_NUMBER:
3361
xmlGenericError(xmlGenericErrorContext,
3362
"%s is a number\n", arg);
3363
break;
3364
case XPATH_STRING:
3365
xmlGenericError(xmlGenericErrorContext,
3366
"%s is a string\n", arg);
3367
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
case XPATH_USERS:
3383
xmlGenericError(xmlGenericErrorContext,
3384
"%s is user-defined\n", arg);
3385
break;
3386
case XPATH_XSLT_TREE:
3387
xmlGenericError(xmlGenericErrorContext,
3388
"%s is an XSLT value tree\n",
3389
arg);
3390
break;
3391
}
3392
#ifdef LIBXML_XPATH_ENABLED
3393
xmlXPathFreeObject(list);
3394
#endif
3395
} else {
3396
xmlGenericError(xmlGenericErrorContext,
3397
"%s: no such node\n", arg);
3398
}
3399
ctxt->pctxt->node = NULL;
3400
}
3401
#endif /* LIBXML_OUTPUT_ENABLED */
3402
} else {
3403
xmlGenericError(xmlGenericErrorContext,
3404
"Unknown command %s\n", command);
3405
}
3406
free(cmdline); /* not xmlFree here ! */
3407
cmdline = NULL;
3408
}
3409
#ifdef LIBXML_XPATH_ENABLED
3410
xmlXPathFreeContext(ctxt->pctxt);
3411
#endif /* LIBXML_XPATH_ENABLED */
3412
if (ctxt->loaded) {
3413
xmlFreeDoc(ctxt->doc);
3414
}
3415
if (ctxt->filename != NULL)
3416
xmlFree(ctxt->filename);
3417
xmlFree(ctxt);
3418
if (cmdline != NULL)
3419
free(cmdline); /* not xmlFree here ! */
3420
}
3421
3422
#endif /* LIBXML_XPATH_ENABLED */
3423
3424
#endif /* LIBXML_DEBUG_ENABLED */
3425
3426