VirtualBox

source: vbox/trunk/src/libs/libxml2-2.13.2/debugXML.c@ 105770

Last change on this file since 105770 was 105420, checked in by vboxsync, 4 months ago

libxml2-2.12.6: Applied and adjusted our libxml2 changes to 2.12.6. bugref:10730

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette