blob: 9b7163d13188dfe76b30da1885f6437ad8dcb39b [file] [log] [blame]
Owen Taylor3473f882001-02-23 17:55:21 +00001/*
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 *
Daniel Veillardc5d64342001-06-24 12:13:24 +00007 * Daniel Veillard <daniel@veillard.com>
Owen Taylor3473f882001-02-23 17:55:21 +00008 */
9
Daniel Veillard34ce8be2002-03-18 19:37:11 +000010#define IN_LIBXML
Bjorn Reese70a9da52001-04-21 16:57:29 +000011#include "libxml.h"
Owen Taylor3473f882001-02-23 17:55:21 +000012#ifdef LIBXML_DEBUG_ENABLED
13
Owen Taylor3473f882001-02-23 17:55:21 +000014#include <string.h>
15#ifdef HAVE_STDLIB_H
16#include <stdlib.h>
17#endif
18#ifdef HAVE_STRING_H
19#include <string.h>
20#endif
21#include <libxml/xmlmemory.h>
22#include <libxml/tree.h>
23#include <libxml/parser.h>
Daniel Veillard567e1b42001-08-01 15:53:47 +000024#include <libxml/parserInternals.h>
Owen Taylor3473f882001-02-23 17:55:21 +000025#include <libxml/valid.h>
26#include <libxml/debugXML.h>
27#include <libxml/HTMLtree.h>
28#include <libxml/HTMLparser.h>
29#include <libxml/xmlerror.h>
Daniel Veillard3c01b1d2001-10-17 15:58:35 +000030#include <libxml/globals.h>
Daniel Veillard0ba59232002-02-10 13:20:39 +000031#include <libxml/xpathInternals.h>
Igor Zlatkovicc06bb622003-04-27 15:59:00 +000032#include <libxml/uri.h>
Daniel Veillard522bc602004-02-21 11:53:09 +000033#ifdef LIBXML_SCHEMAS_ENABLED
34#include <libxml/relaxng.h>
35#endif
Owen Taylor3473f882001-02-23 17:55:21 +000036
Daniel Veillard22cdb842004-10-04 14:09:17 +000037typedef struct _xmlDebugCtxt xmlDebugCtxt;
38typedef xmlDebugCtxt *xmlDebugCtxtPtr;
39struct _xmlDebugCtxt {
40 FILE *output; /* the output file */
41 char shift[101]; /* used for indenting */
42 int depth; /* current depth */
43 xmlDocPtr doc; /* current document */
Daniel Veillard8de5c0b2004-10-07 13:14:19 +000044 xmlNodePtr node; /* current node */
Daniel Veillard22cdb842004-10-04 14:09:17 +000045 int check; /* do just checkings */
Daniel Veillard8de5c0b2004-10-07 13:14:19 +000046 int errors; /* number of errors found */
Daniel Veillard22cdb842004-10-04 14:09:17 +000047};
48
49static void xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node);
50
51static void
52xmlCtxtDumpInitCtxt(xmlDebugCtxtPtr ctxt)
53{
54 int i;
55
56 ctxt->depth = 0;
57 ctxt->check = 0;
Daniel Veillard8de5c0b2004-10-07 13:14:19 +000058 ctxt->errors = 0;
Daniel Veillard22cdb842004-10-04 14:09:17 +000059 ctxt->output = stdout;
60 for (i = 0; i < 100; i++)
61 ctxt->shift[i] = ' ';
62 ctxt->shift[100] = 0;
63}
64
65static void
Daniel Veillard76821142004-10-09 20:39:04 +000066xmlCtxtDumpCleanCtxt(xmlDebugCtxtPtr ctxt)
67{
Daniel Veillard76821142004-10-09 20:39:04 +000068}
69
70/**
Daniel Veillard0d24b112004-10-11 12:28:34 +000071 * xmlNsCheckScope:
72 * @node: the node
73 * @ns: the namespace node
Daniel Veillard76821142004-10-09 20:39:04 +000074 *
Daniel Veillard0d24b112004-10-11 12:28:34 +000075 * Check that a given namespace is in scope on a node.
Daniel Veillard76821142004-10-09 20:39:04 +000076 *
Daniel Veillard0d24b112004-10-11 12:28:34 +000077 * Returns 1 if in scope, -1 in case of argument error,
78 * -2 if the namespace is not in scope, and -3 if not on
79 * an ancestor node.
Daniel Veillard76821142004-10-09 20:39:04 +000080 */
81static int
Daniel Veillard0d24b112004-10-11 12:28:34 +000082xmlNsCheckScope(xmlNodePtr node, xmlNsPtr ns)
Daniel Veillard76821142004-10-09 20:39:04 +000083{
Daniel Veillard0d24b112004-10-11 12:28:34 +000084 xmlNsPtr cur;
Daniel Veillard76821142004-10-09 20:39:04 +000085
Daniel Veillard0d24b112004-10-11 12:28:34 +000086 if ((node == NULL) || (ns == NULL))
87 return(-1);
88
89 if ((node->type != XML_ELEMENT_NODE) &&
90 (node->type != XML_ATTRIBUTE_NODE) &&
91 (node->type != XML_DOCUMENT_NODE) &&
92 (node->type != XML_TEXT_NODE) &&
93 (node->type != XML_HTML_DOCUMENT_NODE) &&
94 (node->type != XML_XINCLUDE_START))
95 return(-2);
96
97 while ((node != NULL) &&
98 ((node->type == XML_ELEMENT_NODE) ||
99 (node->type == XML_ATTRIBUTE_NODE) ||
100 (node->type == XML_TEXT_NODE) ||
101 (node->type == XML_XINCLUDE_START))) {
102 if ((node->type == XML_ELEMENT_NODE) ||
103 (node->type == XML_XINCLUDE_START)) {
104 cur = node->nsDef;
105 while (cur != NULL) {
106 if (cur == ns)
107 return(1);
108 if (xmlStrEqual(cur->prefix, ns->prefix))
109 return(-2);
110 cur = cur->next;
111 }
Daniel Veillard76821142004-10-09 20:39:04 +0000112 }
Daniel Veillard0d24b112004-10-11 12:28:34 +0000113 node = node->parent;
Daniel Veillard76821142004-10-09 20:39:04 +0000114 }
Daniel Veillard0d24b112004-10-11 12:28:34 +0000115 /* the xml namespace may be declared on the document node */
116 if ((node != NULL) &&
117 ((node->type == XML_DOCUMENT_NODE) ||
118 (node->type == XML_HTML_DOCUMENT_NODE))) {
119 xmlNsPtr oldNs = ((xmlDocPtr) node)->oldNs;
120 if (oldNs == ns)
121 return(1);
122 }
123 return(-3);
Daniel Veillard76821142004-10-09 20:39:04 +0000124}
Daniel Veillard76821142004-10-09 20:39:04 +0000125
Daniel Veillard76821142004-10-09 20:39:04 +0000126static void
Daniel Veillard22cdb842004-10-04 14:09:17 +0000127xmlCtxtDumpSpaces(xmlDebugCtxtPtr ctxt)
128{
129 if (ctxt->check)
130 return;
131 if ((ctxt->output != NULL) && (ctxt->depth > 0)) {
132 if (ctxt->depth < 50)
133 fprintf(ctxt->output, &ctxt->shift[100 - 2 * ctxt->depth]);
134 else
135 fprintf(ctxt->output, ctxt->shift);
136 }
137}
138
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000139/**
140 * xmlDebugErr:
141 * @ctxt: a debug context
142 * @error: the error code
143 *
144 * Handle a debug error.
145 */
146static void
147xmlDebugErr(xmlDebugCtxtPtr ctxt, int error, const char *msg)
148{
149 ctxt->errors++;
150 __xmlRaiseError(NULL, NULL, NULL,
151 NULL, ctxt->node, XML_FROM_CHECK,
152 error, XML_ERR_ERROR, NULL, 0,
153 NULL, NULL, NULL, 0, 0,
154 msg);
155}
156static void
157xmlDebugErr2(xmlDebugCtxtPtr ctxt, int error, const char *msg, int extra)
158{
159 ctxt->errors++;
160 __xmlRaiseError(NULL, NULL, NULL,
161 NULL, ctxt->node, XML_FROM_CHECK,
162 error, XML_ERR_ERROR, NULL, 0,
163 NULL, NULL, NULL, 0, 0,
164 msg, extra);
165}
166static void
Daniel Veillardc6095782004-10-15 14:50:10 +0000167xmlDebugErr3(xmlDebugCtxtPtr ctxt, int error, const char *msg, const char *extra)
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000168{
169 ctxt->errors++;
170 __xmlRaiseError(NULL, NULL, NULL,
171 NULL, ctxt->node, XML_FROM_CHECK,
172 error, XML_ERR_ERROR, NULL, 0,
173 NULL, NULL, NULL, 0, 0,
174 msg, extra);
175}
176
Daniel Veillard0d24b112004-10-11 12:28:34 +0000177/**
178 * xmlCtxtNsCheckScope:
179 * @ctxt: the debugging context
180 * @node: the node
181 * @ns: the namespace node
182 *
183 * Report if a given namespace is is not in scope.
184 */
185static void
186xmlCtxtNsCheckScope(xmlDebugCtxtPtr ctxt, xmlNodePtr node, xmlNsPtr ns)
187{
188 int ret;
189
190 ret = xmlNsCheckScope(node, ns);
191 if (ret == -2) {
192 if (ns->prefix == NULL)
193 xmlDebugErr(ctxt, XML_CHECK_NS_SCOPE,
194 "Reference to default namespace not in scope\n");
195 else
196 xmlDebugErr3(ctxt, XML_CHECK_NS_SCOPE,
197 "Reference to namespace '%s' not in scope\n",
198 (char *) ns->prefix);
199 }
200 if (ret == -3) {
201 if (ns->prefix == NULL)
202 xmlDebugErr(ctxt, XML_CHECK_NS_ANCESTOR,
203 "Reference to default namespace not on ancestor\n");
204 else
205 xmlDebugErr3(ctxt, XML_CHECK_NS_ANCESTOR,
206 "Reference to namespace '%s' not on ancestor\n",
207 (char *) ns->prefix);
208 }
209}
210
Daniel Veillardc6095782004-10-15 14:50:10 +0000211/**
212 * xmlCtxtCheckString:
213 * @ctxt: the debug context
214 * @str: the string
215 *
216 * Do debugging on the string, currently it just checks the UTF-8 content
217 */
218static void
219xmlCtxtCheckString(xmlDebugCtxtPtr ctxt, const xmlChar * str)
220{
221 if (str == NULL) return;
222 if (ctxt->check) {
223 if (!xmlCheckUTF8(str)) {
224 xmlDebugErr3(ctxt, XML_CHECK_NOT_DTD,
225 "String is not UTF-8 %s", (const char *) str);
226 }
227 }
228}
229
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000230static void
231xmlCtxtGenericNodeCheck(xmlDebugCtxtPtr ctxt, xmlNodePtr node) {
232 if (node->parent == NULL)
233 xmlDebugErr(ctxt, XML_CHECK_NO_PARENT,
234 "Node has no parent\n");
235 if (node->doc == NULL)
236 xmlDebugErr(ctxt, XML_CHECK_NO_DOC,
237 "Node has no doc\n");
238 if ((node->parent != NULL) && (node->doc != node->parent->doc) &&
239 (!xmlStrEqual(node->name, BAD_CAST "pseudoroot")))
240 xmlDebugErr(ctxt, XML_CHECK_WRONG_DOC,
241 "Node doc differs from parent's one\n");
242 if (node->prev == NULL) {
243 if (node->type == XML_ATTRIBUTE_NODE) {
244 if ((node->parent != NULL) &&
245 (node != (xmlNodePtr) node->parent->properties))
246 xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
247 "Attr has no prev and not first of attr list\n");
248
249 } else if ((node->parent != NULL) && (node->parent->children != node))
250 xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
251 "Node has no prev and not first of parent list\n");
252 } else {
253 if (node->prev->next != node)
254 xmlDebugErr(ctxt, XML_CHECK_WRONG_PREV,
255 "Node prev->next : back link wrong\n");
256 }
257 if (node->next == NULL) {
258 if ((node->parent != NULL) && (node->type != XML_ATTRIBUTE_NODE) &&
259 (node->parent->last != node))
260 xmlDebugErr(ctxt, XML_CHECK_NO_NEXT,
261 "Node has no next and not last of parent list\n");
262 } else {
263 if (node->next->prev != node)
264 xmlDebugErr(ctxt, XML_CHECK_WRONG_NEXT,
265 "Node next->prev : forward link wrong\n");
Daniel Veillard0d24b112004-10-11 12:28:34 +0000266 if (node->next->parent != node->parent)
267 xmlDebugErr(ctxt, XML_CHECK_WRONG_PARENT,
268 "Node next->prev : forward link wrong\n");
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000269 }
Daniel Veillard0d24b112004-10-11 12:28:34 +0000270 if (node->type == XML_ELEMENT_NODE) {
271 xmlNsPtr ns;
272
273 ns = node->nsDef;
274 while (ns != NULL) {
275 xmlCtxtNsCheckScope(ctxt, node, ns);
276 ns = ns->next;
277 }
278 if (node->ns != NULL)
279 xmlCtxtNsCheckScope(ctxt, node, node->ns);
280 } else if (node->type == XML_ATTRIBUTE_NODE) {
281 if (node->ns != NULL)
282 xmlCtxtNsCheckScope(ctxt, node, node->ns);
283 }
284
Daniel Veillardc6095782004-10-15 14:50:10 +0000285 if ((node->type != XML_ELEMENT_NODE) &&
286 (node->type != XML_HTML_DOCUMENT_NODE) &&
287 (node->type != XML_DOCUMENT_NODE)) {
288 if (node->content != NULL)
289 xmlCtxtCheckString(ctxt, (const char *) node->content);
290 }
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000291}
292
Daniel Veillard22cdb842004-10-04 14:09:17 +0000293static void
294xmlCtxtDumpString(xmlDebugCtxtPtr ctxt, const xmlChar * str)
295{
296 int i;
297
Daniel Veillardc6095782004-10-15 14:50:10 +0000298 if (ctxt->check) {
Daniel Veillard22cdb842004-10-04 14:09:17 +0000299 return;
Daniel Veillardc6095782004-10-15 14:50:10 +0000300 }
Daniel Veillard22cdb842004-10-04 14:09:17 +0000301 /* TODO: check UTF8 content of the string */
302 if (str == NULL) {
303 fprintf(ctxt->output, "(NULL)");
304 return;
305 }
306 for (i = 0; i < 40; i++)
307 if (str[i] == 0)
308 return;
309 else if (IS_BLANK_CH(str[i]))
310 fputc(' ', ctxt->output);
311 else if (str[i] >= 0x80)
312 fprintf(ctxt->output, "#%X", str[i]);
313 else
314 fputc(str[i], ctxt->output);
315 fprintf(ctxt->output, "...");
316}
317
318static void
319xmlCtxtDumpDtdNode(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd)
320{
321 xmlCtxtDumpSpaces(ctxt);
322
323 if (dtd == NULL) {
324 if (!ctxt->check)
325 fprintf(ctxt->output, "DTD node is NULL\n");
326 return;
327 }
328
329 if (dtd->type != XML_DTD_NODE) {
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000330 xmlDebugErr(ctxt, XML_CHECK_NOT_DTD,
331 "Node is not a DTD");
Daniel Veillard22cdb842004-10-04 14:09:17 +0000332 return;
333 }
334 if (!ctxt->check) {
335 if (dtd->name != NULL)
336 fprintf(ctxt->output, "DTD(%s)", (char *) dtd->name);
337 else
338 fprintf(ctxt->output, "DTD");
339 if (dtd->ExternalID != NULL)
340 fprintf(ctxt->output, ", PUBLIC %s", (char *) dtd->ExternalID);
341 if (dtd->SystemID != NULL)
342 fprintf(ctxt->output, ", SYSTEM %s", (char *) dtd->SystemID);
343 fprintf(ctxt->output, "\n");
344 }
345 /*
346 * Do a bit of checking
347 */
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000348 xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) dtd);
Daniel Veillard22cdb842004-10-04 14:09:17 +0000349}
350
351static void
352xmlCtxtDumpAttrDecl(xmlDebugCtxtPtr ctxt, xmlAttributePtr attr)
353{
354 xmlCtxtDumpSpaces(ctxt);
355
356 if (attr == NULL) {
357 if (!ctxt->check)
358 fprintf(ctxt->output, "Attribute declaration is NULL\n");
359 return;
360 }
361 if (attr->type != XML_ATTRIBUTE_DECL) {
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000362 xmlDebugErr(ctxt, XML_CHECK_NOT_ATTR_DECL,
363 "Node is not an attribute declaration");
Daniel Veillard22cdb842004-10-04 14:09:17 +0000364 return;
365 }
366 if (attr->name != NULL) {
367 if (!ctxt->check)
368 fprintf(ctxt->output, "ATTRDECL(%s)", (char *) attr->name);
369 } else
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000370 xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
371 "Node attribute declaration has no name");
Daniel Veillard22cdb842004-10-04 14:09:17 +0000372 if (attr->elem != NULL) {
373 if (!ctxt->check)
374 fprintf(ctxt->output, " for %s", (char *) attr->elem);
375 } else
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000376 xmlDebugErr(ctxt, XML_CHECK_NO_ELEM,
377 "Node attribute declaration has no element name");
Daniel Veillard22cdb842004-10-04 14:09:17 +0000378 if (!ctxt->check) {
379 switch (attr->atype) {
380 case XML_ATTRIBUTE_CDATA:
381 fprintf(ctxt->output, " CDATA");
382 break;
383 case XML_ATTRIBUTE_ID:
384 fprintf(ctxt->output, " ID");
385 break;
386 case XML_ATTRIBUTE_IDREF:
387 fprintf(ctxt->output, " IDREF");
388 break;
389 case XML_ATTRIBUTE_IDREFS:
390 fprintf(ctxt->output, " IDREFS");
391 break;
392 case XML_ATTRIBUTE_ENTITY:
393 fprintf(ctxt->output, " ENTITY");
394 break;
395 case XML_ATTRIBUTE_ENTITIES:
396 fprintf(ctxt->output, " ENTITIES");
397 break;
398 case XML_ATTRIBUTE_NMTOKEN:
399 fprintf(ctxt->output, " NMTOKEN");
400 break;
401 case XML_ATTRIBUTE_NMTOKENS:
402 fprintf(ctxt->output, " NMTOKENS");
403 break;
404 case XML_ATTRIBUTE_ENUMERATION:
405 fprintf(ctxt->output, " ENUMERATION");
406 break;
407 case XML_ATTRIBUTE_NOTATION:
408 fprintf(ctxt->output, " NOTATION ");
409 break;
410 }
411 if (attr->tree != NULL) {
412 int indx;
413 xmlEnumerationPtr cur = attr->tree;
414
415 for (indx = 0; indx < 5; indx++) {
416 if (indx != 0)
417 fprintf(ctxt->output, "|%s", (char *) cur->name);
418 else
419 fprintf(ctxt->output, " (%s", (char *) cur->name);
420 cur = cur->next;
421 if (cur == NULL)
422 break;
423 }
424 if (cur == NULL)
425 fprintf(ctxt->output, ")");
426 else
427 fprintf(ctxt->output, "...)");
428 }
429 switch (attr->def) {
430 case XML_ATTRIBUTE_NONE:
431 break;
432 case XML_ATTRIBUTE_REQUIRED:
433 fprintf(ctxt->output, " REQUIRED");
434 break;
435 case XML_ATTRIBUTE_IMPLIED:
436 fprintf(ctxt->output, " IMPLIED");
437 break;
438 case XML_ATTRIBUTE_FIXED:
439 fprintf(ctxt->output, " FIXED");
440 break;
441 }
442 if (attr->defaultValue != NULL) {
443 fprintf(ctxt->output, "\"");
444 xmlCtxtDumpString(ctxt, attr->defaultValue);
445 fprintf(ctxt->output, "\"");
446 }
447 fprintf(ctxt->output, "\n");
448 }
449
450 /*
451 * Do a bit of checking
452 */
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000453 xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr);
Daniel Veillard22cdb842004-10-04 14:09:17 +0000454}
455
456static void
457xmlCtxtDumpElemDecl(xmlDebugCtxtPtr ctxt, xmlElementPtr elem)
458{
459 xmlCtxtDumpSpaces(ctxt);
460
461 if (elem == NULL) {
462 if (!ctxt->check)
463 fprintf(ctxt->output, "Element declaration is NULL\n");
464 return;
465 }
466 if (elem->type != XML_ELEMENT_DECL) {
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000467 xmlDebugErr(ctxt, XML_CHECK_NOT_ELEM_DECL,
468 "Node is not an element declaration");
Daniel Veillard22cdb842004-10-04 14:09:17 +0000469 return;
470 }
471 if (elem->name != NULL) {
472 if (!ctxt->check) {
473 fprintf(ctxt->output, "ELEMDECL(");
474 xmlCtxtDumpString(ctxt, elem->name);
475 fprintf(ctxt->output, ")");
476 }
477 } else
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000478 xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
479 "Element declaration has no name");
Daniel Veillard22cdb842004-10-04 14:09:17 +0000480 if (!ctxt->check) {
481 switch (elem->etype) {
482 case XML_ELEMENT_TYPE_UNDEFINED:
483 fprintf(ctxt->output, ", UNDEFINED");
484 break;
485 case XML_ELEMENT_TYPE_EMPTY:
486 fprintf(ctxt->output, ", EMPTY");
487 break;
488 case XML_ELEMENT_TYPE_ANY:
489 fprintf(ctxt->output, ", ANY");
490 break;
491 case XML_ELEMENT_TYPE_MIXED:
492 fprintf(ctxt->output, ", MIXED ");
493 break;
494 case XML_ELEMENT_TYPE_ELEMENT:
495 fprintf(ctxt->output, ", MIXED ");
496 break;
497 }
498 if ((elem->type != XML_ELEMENT_NODE) && (elem->content != NULL)) {
499 char buf[5001];
500
501 buf[0] = 0;
502 xmlSnprintfElementContent(buf, 5000, elem->content, 1);
503 buf[5000] = 0;
504 fprintf(ctxt->output, "%s", buf);
505 }
506 fprintf(ctxt->output, "\n");
507 }
508
509 /*
510 * Do a bit of checking
511 */
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000512 xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) elem);
Daniel Veillard22cdb842004-10-04 14:09:17 +0000513}
514
515static void
516xmlCtxtDumpEntityDecl(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent)
517{
518 xmlCtxtDumpSpaces(ctxt);
519
520 if (ent == NULL) {
521 if (!ctxt->check)
522 fprintf(ctxt->output, "Entity declaration is NULL\n");
523 return;
524 }
525 if (ent->type != XML_ENTITY_DECL) {
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000526 xmlDebugErr(ctxt, XML_CHECK_NOT_ENTITY_DECL,
527 "Node is not an entity declaration");
Daniel Veillard22cdb842004-10-04 14:09:17 +0000528 return;
529 }
530 if (ent->name != NULL) {
531 if (!ctxt->check) {
532 fprintf(ctxt->output, "ENTITYDECL(");
533 xmlCtxtDumpString(ctxt, ent->name);
534 fprintf(ctxt->output, ")");
535 }
536 } else
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000537 xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
538 "Entity declaration has no name");
Daniel Veillard22cdb842004-10-04 14:09:17 +0000539 if (!ctxt->check) {
540 switch (ent->etype) {
541 case XML_INTERNAL_GENERAL_ENTITY:
542 fprintf(ctxt->output, ", internal\n");
543 break;
544 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
545 fprintf(ctxt->output, ", external parsed\n");
546 break;
547 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
548 fprintf(ctxt->output, ", unparsed\n");
549 break;
550 case XML_INTERNAL_PARAMETER_ENTITY:
551 fprintf(ctxt->output, ", parameter\n");
552 break;
553 case XML_EXTERNAL_PARAMETER_ENTITY:
554 fprintf(ctxt->output, ", external parameter\n");
555 break;
556 case XML_INTERNAL_PREDEFINED_ENTITY:
557 fprintf(ctxt->output, ", predefined\n");
558 break;
559 }
560 if (ent->ExternalID) {
561 xmlCtxtDumpSpaces(ctxt);
562 fprintf(ctxt->output, " ExternalID=%s\n",
563 (char *) ent->ExternalID);
564 }
565 if (ent->SystemID) {
566 xmlCtxtDumpSpaces(ctxt);
567 fprintf(ctxt->output, " SystemID=%s\n",
568 (char *) ent->SystemID);
569 }
570 if (ent->URI != NULL) {
571 xmlCtxtDumpSpaces(ctxt);
572 fprintf(ctxt->output, " URI=%s\n", (char *) ent->URI);
573 }
574 if (ent->content) {
575 xmlCtxtDumpSpaces(ctxt);
576 fprintf(ctxt->output, " content=");
577 xmlCtxtDumpString(ctxt, ent->content);
578 fprintf(ctxt->output, "\n");
579 }
580 }
581
582 /*
583 * Do a bit of checking
584 */
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000585 xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) ent);
Daniel Veillard22cdb842004-10-04 14:09:17 +0000586}
587
588static void
589xmlCtxtDumpNamespace(xmlDebugCtxtPtr ctxt, xmlNsPtr ns)
590{
591 xmlCtxtDumpSpaces(ctxt);
592
593 if (ns == NULL) {
594 if (!ctxt->check)
595 fprintf(ctxt->output, "namespace node is NULL\n");
596 return;
597 }
598 if (ns->type != XML_NAMESPACE_DECL) {
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000599 xmlDebugErr(ctxt, XML_CHECK_NOT_NS_DECL,
600 "Node is not a namespace declaration");
Daniel Veillard22cdb842004-10-04 14:09:17 +0000601 return;
602 }
603 if (ns->href == NULL) {
604 if (ns->prefix != NULL)
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000605 xmlDebugErr3(ctxt, XML_CHECK_NO_HREF,
606 "Incomplete namespace %s href=NULL\n",
Daniel Veillard22cdb842004-10-04 14:09:17 +0000607 (char *) ns->prefix);
608 else
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000609 xmlDebugErr(ctxt, XML_CHECK_NO_HREF,
610 "Incomplete default namespace href=NULL\n");
Daniel Veillard22cdb842004-10-04 14:09:17 +0000611 } else {
612 if (!ctxt->check) {
613 if (ns->prefix != NULL)
614 fprintf(ctxt->output, "namespace %s href=",
615 (char *) ns->prefix);
616 else
617 fprintf(ctxt->output, "default namespace href=");
618
619 xmlCtxtDumpString(ctxt, ns->href);
620 fprintf(ctxt->output, "\n");
621 }
622 }
623}
624
625static void
626xmlCtxtDumpNamespaceList(xmlDebugCtxtPtr ctxt, xmlNsPtr ns)
627{
628 while (ns != NULL) {
629 xmlCtxtDumpNamespace(ctxt, ns);
630 ns = ns->next;
631 }
632}
633
634static void
635xmlCtxtDumpEntity(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent)
636{
637 xmlCtxtDumpSpaces(ctxt);
638
639 if (ent == NULL) {
640 if (!ctxt->check)
641 fprintf(ctxt->output, "Entity is NULL\n");
642 return;
643 }
644 if (!ctxt->check) {
645 switch (ent->etype) {
646 case XML_INTERNAL_GENERAL_ENTITY:
647 fprintf(ctxt->output, "INTERNAL_GENERAL_ENTITY ");
648 break;
649 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
650 fprintf(ctxt->output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
651 break;
652 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
653 fprintf(ctxt->output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
654 break;
655 case XML_INTERNAL_PARAMETER_ENTITY:
656 fprintf(ctxt->output, "INTERNAL_PARAMETER_ENTITY ");
657 break;
658 case XML_EXTERNAL_PARAMETER_ENTITY:
659 fprintf(ctxt->output, "EXTERNAL_PARAMETER_ENTITY ");
660 break;
661 default:
662 fprintf(ctxt->output, "ENTITY_%d ! ", (int) ent->etype);
663 }
664 fprintf(ctxt->output, "%s\n", ent->name);
665 if (ent->ExternalID) {
666 xmlCtxtDumpSpaces(ctxt);
667 fprintf(ctxt->output, "ExternalID=%s\n",
668 (char *) ent->ExternalID);
669 }
670 if (ent->SystemID) {
671 xmlCtxtDumpSpaces(ctxt);
672 fprintf(ctxt->output, "SystemID=%s\n", (char *) ent->SystemID);
673 }
674 if (ent->URI) {
675 xmlCtxtDumpSpaces(ctxt);
676 fprintf(ctxt->output, "URI=%s\n", (char *) ent->URI);
677 }
678 if (ent->content) {
679 xmlCtxtDumpSpaces(ctxt);
680 fprintf(ctxt->output, "content=");
681 xmlCtxtDumpString(ctxt, ent->content);
682 fprintf(ctxt->output, "\n");
683 }
684 }
685}
686
687/**
688 * xmlCtxtDumpAttr:
689 * @output: the FILE * for the output
690 * @attr: the attribute
691 * @depth: the indentation level.
692 *
693 * Dumps debug information for the attribute
694 */
695static void
696xmlCtxtDumpAttr(xmlDebugCtxtPtr ctxt, xmlAttrPtr attr)
697{
698 xmlCtxtDumpSpaces(ctxt);
699
700 if (attr == NULL) {
701 if (!ctxt->check)
702 fprintf(ctxt->output, "Attr is NULL");
703 return;
704 }
705 if (!ctxt->check) {
706 fprintf(ctxt->output, "ATTRIBUTE ");
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000707 xmlCtxtDumpString(ctxt, attr->name);
Daniel Veillard22cdb842004-10-04 14:09:17 +0000708 fprintf(ctxt->output, "\n");
709 if (attr->children != NULL) {
710 ctxt->depth++;
711 xmlCtxtDumpNodeList(ctxt, attr->children);
712 ctxt->depth--;
713 }
714 }
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000715 if (attr->name == NULL)
716 xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
717 "Attribute has no name");
Daniel Veillard22cdb842004-10-04 14:09:17 +0000718
719 /*
720 * Do a bit of checking
721 */
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000722 xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr);
Daniel Veillard22cdb842004-10-04 14:09:17 +0000723}
724
725/**
726 * xmlCtxtDumpAttrList:
727 * @output: the FILE * for the output
728 * @attr: the attribute list
729 * @depth: the indentation level.
730 *
731 * Dumps debug information for the attribute list
732 */
733static void
734xmlCtxtDumpAttrList(xmlDebugCtxtPtr ctxt, xmlAttrPtr attr)
735{
736 while (attr != NULL) {
737 xmlCtxtDumpAttr(ctxt, attr);
738 attr = attr->next;
739 }
740}
741
742/**
743 * xmlCtxtDumpOneNode:
744 * @output: the FILE * for the output
745 * @node: the node
746 * @depth: the indentation level.
747 *
748 * Dumps debug information for the element node, it is not recursive
749 */
750static void
751xmlCtxtDumpOneNode(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
752{
753 if (node == NULL) {
754 if (!ctxt->check) {
755 xmlCtxtDumpSpaces(ctxt);
756 fprintf(ctxt->output, "node is NULL\n");
757 }
758 return;
759 }
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000760 ctxt->node = node;
761
Daniel Veillard22cdb842004-10-04 14:09:17 +0000762 switch (node->type) {
763 case XML_ELEMENT_NODE:
764 if (!ctxt->check) {
765 xmlCtxtDumpSpaces(ctxt);
766 fprintf(ctxt->output, "ELEMENT ");
767 if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
768 xmlCtxtDumpString(ctxt, node->ns->prefix);
769 fprintf(ctxt->output, ":");
770 }
771 xmlCtxtDumpString(ctxt, node->name);
772 fprintf(ctxt->output, "\n");
773 }
774 break;
775 case XML_ATTRIBUTE_NODE:
776 if (!ctxt->check)
777 xmlCtxtDumpSpaces(ctxt);
778 fprintf(ctxt->output, "Error, ATTRIBUTE found here\n");
779 break;
780 case XML_TEXT_NODE:
781 if (!ctxt->check) {
782 xmlCtxtDumpSpaces(ctxt);
783 if (node->name == (const xmlChar *) xmlStringTextNoenc)
784 fprintf(ctxt->output, "TEXT no enc\n");
785 else
786 fprintf(ctxt->output, "TEXT\n");
787 }
788 break;
789 case XML_CDATA_SECTION_NODE:
790 if (!ctxt->check) {
791 xmlCtxtDumpSpaces(ctxt);
792 fprintf(ctxt->output, "CDATA_SECTION\n");
793 }
794 break;
795 case XML_ENTITY_REF_NODE:
796 if (!ctxt->check) {
797 xmlCtxtDumpSpaces(ctxt);
798 fprintf(ctxt->output, "ENTITY_REF(%s)\n",
799 (char *) node->name);
800 }
801 break;
802 case XML_ENTITY_NODE:
803 if (!ctxt->check) {
804 xmlCtxtDumpSpaces(ctxt);
805 fprintf(ctxt->output, "ENTITY\n");
806 }
807 break;
808 case XML_PI_NODE:
809 if (!ctxt->check) {
810 xmlCtxtDumpSpaces(ctxt);
811 fprintf(ctxt->output, "PI %s\n", (char *) node->name);
812 }
813 break;
814 case XML_COMMENT_NODE:
815 if (!ctxt->check) {
816 xmlCtxtDumpSpaces(ctxt);
817 fprintf(ctxt->output, "COMMENT\n");
818 }
819 break;
820 case XML_DOCUMENT_NODE:
821 case XML_HTML_DOCUMENT_NODE:
822 if (!ctxt->check) {
823 xmlCtxtDumpSpaces(ctxt);
824 }
825 fprintf(ctxt->output, "PBM: DOCUMENT found here\n");
826 break;
827 case XML_DOCUMENT_TYPE_NODE:
828 if (!ctxt->check) {
829 xmlCtxtDumpSpaces(ctxt);
830 fprintf(ctxt->output, "DOCUMENT_TYPE\n");
831 }
832 break;
833 case XML_DOCUMENT_FRAG_NODE:
834 if (!ctxt->check) {
835 xmlCtxtDumpSpaces(ctxt);
836 fprintf(ctxt->output, "DOCUMENT_FRAG\n");
837 }
838 break;
839 case XML_NOTATION_NODE:
840 if (!ctxt->check) {
841 xmlCtxtDumpSpaces(ctxt);
842 fprintf(ctxt->output, "NOTATION\n");
843 }
844 break;
845 case XML_DTD_NODE:
846 xmlCtxtDumpDtdNode(ctxt, (xmlDtdPtr) node);
847 return;
848 case XML_ELEMENT_DECL:
849 xmlCtxtDumpElemDecl(ctxt, (xmlElementPtr) node);
850 return;
851 case XML_ATTRIBUTE_DECL:
852 xmlCtxtDumpAttrDecl(ctxt, (xmlAttributePtr) node);
853 return;
854 case XML_ENTITY_DECL:
855 xmlCtxtDumpEntityDecl(ctxt, (xmlEntityPtr) node);
856 return;
857 case XML_NAMESPACE_DECL:
858 xmlCtxtDumpNamespace(ctxt, (xmlNsPtr) node);
859 return;
860 case XML_XINCLUDE_START:
861 if (!ctxt->check) {
862 xmlCtxtDumpSpaces(ctxt);
863 fprintf(ctxt->output, "INCLUDE START\n");
864 }
865 return;
866 case XML_XINCLUDE_END:
867 if (!ctxt->check) {
868 xmlCtxtDumpSpaces(ctxt);
869 fprintf(ctxt->output, "INCLUDE END\n");
870 }
871 return;
872 default:
873 if (!ctxt->check)
874 xmlCtxtDumpSpaces(ctxt);
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000875 xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE,
876 "Unknown node type %d\n", node->type);
Daniel Veillard22cdb842004-10-04 14:09:17 +0000877 return;
878 }
879 if (node->doc == NULL) {
880 if (!ctxt->check) {
881 xmlCtxtDumpSpaces(ctxt);
882 }
883 fprintf(ctxt->output, "PBM: doc == NULL !!!\n");
884 }
885 ctxt->depth++;
886 if (node->nsDef != NULL)
887 xmlCtxtDumpNamespaceList(ctxt, node->nsDef);
888 if (node->properties != NULL)
889 xmlCtxtDumpAttrList(ctxt, node->properties);
890 if (node->type != XML_ENTITY_REF_NODE) {
891 if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
892 if (!ctxt->check) {
893 xmlCtxtDumpSpaces(ctxt);
894 fprintf(ctxt->output, "content=");
895 xmlCtxtDumpString(ctxt, node->content);
896 fprintf(ctxt->output, "\n");
897 }
898 }
899 } else {
900 xmlEntityPtr ent;
901
902 ent = xmlGetDocEntity(node->doc, node->name);
903 if (ent != NULL)
904 xmlCtxtDumpEntity(ctxt, ent);
905 }
906 ctxt->depth--;
907
908 /*
909 * Do a bit of checking
910 */
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000911 xmlCtxtGenericNodeCheck(ctxt, node);
Daniel Veillard22cdb842004-10-04 14:09:17 +0000912}
913
914/**
915 * xmlCtxtDumpNode:
916 * @output: the FILE * for the output
917 * @node: the node
918 * @depth: the indentation level.
919 *
920 * Dumps debug information for the element node, it is recursive
921 */
922static void
923xmlCtxtDumpNode(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
924{
925 if (node == NULL) {
926 if (!ctxt->check) {
927 xmlCtxtDumpSpaces(ctxt);
928 fprintf(ctxt->output, "node is NULL\n");
929 }
930 return;
931 }
932 xmlCtxtDumpOneNode(ctxt, node);
933 if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
934 ctxt->depth++;
935 xmlCtxtDumpNodeList(ctxt, node->children);
936 ctxt->depth--;
937 }
938}
939
940/**
941 * xmlCtxtDumpNodeList:
942 * @output: the FILE * for the output
943 * @node: the node list
944 * @depth: the indentation level.
945 *
946 * Dumps debug information for the list of element node, it is recursive
947 */
948static void
949xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
950{
951 while (node != NULL) {
952 xmlCtxtDumpNode(ctxt, node);
953 node = node->next;
954 }
955}
956
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000957static void
958xmlCtxtDumpDocHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
959{
960 if (doc == NULL) {
961 if (!ctxt->check)
962 fprintf(ctxt->output, "DOCUMENT == NULL !\n");
963 return;
964 }
965 ctxt->node = (xmlNodePtr) doc;
966
967 switch (doc->type) {
968 case XML_ELEMENT_NODE:
969 xmlDebugErr(ctxt, XML_CHECK_FOUND_ELEMENT,
970 "Misplaced ELEMENT node\n");
971 break;
972 case XML_ATTRIBUTE_NODE:
973 xmlDebugErr(ctxt, XML_CHECK_FOUND_ATTRIBUTE,
974 "Misplaced ATTRIBUTE node\n");
975 break;
976 case XML_TEXT_NODE:
977 xmlDebugErr(ctxt, XML_CHECK_FOUND_TEXT,
978 "Misplaced TEXT node\n");
979 break;
980 case XML_CDATA_SECTION_NODE:
981 xmlDebugErr(ctxt, XML_CHECK_FOUND_CDATA,
982 "Misplaced CDATA node\n");
983 break;
984 case XML_ENTITY_REF_NODE:
985 xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITYREF,
986 "Misplaced ENTITYREF node\n");
987 break;
988 case XML_ENTITY_NODE:
989 xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITY,
990 "Misplaced ENTITY node\n");
991 break;
992 case XML_PI_NODE:
993 xmlDebugErr(ctxt, XML_CHECK_FOUND_PI,
994 "Misplaced PI node\n");
995 break;
996 case XML_COMMENT_NODE:
997 xmlDebugErr(ctxt, XML_CHECK_FOUND_COMMENT,
998 "Misplaced COMMENT node\n");
999 break;
1000 case XML_DOCUMENT_NODE:
1001 if (!ctxt->check)
1002 fprintf(ctxt->output, "DOCUMENT\n");
1003 break;
1004 case XML_HTML_DOCUMENT_NODE:
1005 if (!ctxt->check)
1006 fprintf(ctxt->output, "HTML DOCUMENT\n");
1007 break;
1008 case XML_DOCUMENT_TYPE_NODE:
1009 xmlDebugErr(ctxt, XML_CHECK_FOUND_DOCTYPE,
1010 "Misplaced DOCTYPE node\n");
1011 break;
1012 case XML_DOCUMENT_FRAG_NODE:
1013 xmlDebugErr(ctxt, XML_CHECK_FOUND_FRAGMENT,
1014 "Misplaced FRAGMENT node\n");
1015 break;
1016 case XML_NOTATION_NODE:
1017 xmlDebugErr(ctxt, XML_CHECK_FOUND_NOTATION,
1018 "Misplaced NOTATION node\n");
1019 break;
1020 default:
1021 xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE,
1022 "Unknown node type %d\n", doc->type);
1023 }
1024}
Daniel Veillard22cdb842004-10-04 14:09:17 +00001025
1026/**
1027 * xmlCtxtDumpDocumentHead:
1028 * @output: the FILE * for the output
1029 * @doc: the document
1030 *
1031 * Dumps debug information cncerning the document, not recursive
1032 */
1033static void
1034xmlCtxtDumpDocumentHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1035{
Daniel Veillard8de5c0b2004-10-07 13:14:19 +00001036 xmlCtxtDumpDocHead(ctxt, doc);
Daniel Veillard22cdb842004-10-04 14:09:17 +00001037 if (!ctxt->check) {
1038 if (doc->name != NULL) {
1039 fprintf(ctxt->output, "name=");
1040 xmlCtxtDumpString(ctxt, BAD_CAST doc->name);
1041 fprintf(ctxt->output, "\n");
1042 }
1043 if (doc->version != NULL) {
1044 fprintf(ctxt->output, "version=");
1045 xmlCtxtDumpString(ctxt, doc->version);
1046 fprintf(ctxt->output, "\n");
1047 }
1048 if (doc->encoding != NULL) {
1049 fprintf(ctxt->output, "encoding=");
1050 xmlCtxtDumpString(ctxt, doc->encoding);
1051 fprintf(ctxt->output, "\n");
1052 }
1053 if (doc->URL != NULL) {
1054 fprintf(ctxt->output, "URL=");
1055 xmlCtxtDumpString(ctxt, doc->URL);
1056 fprintf(ctxt->output, "\n");
1057 }
1058 if (doc->standalone)
1059 fprintf(ctxt->output, "standalone=true\n");
1060 }
1061 if (doc->oldNs != NULL)
1062 xmlCtxtDumpNamespaceList(ctxt, doc->oldNs);
1063}
1064
1065/**
1066 * xmlCtxtDumpDocument:
1067 * @output: the FILE * for the output
1068 * @doc: the document
1069 *
1070 * Dumps debug information for the document, it's recursive
1071 */
1072static void
1073xmlCtxtDumpDocument(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1074{
1075 if (doc == NULL) {
1076 if (!ctxt->check)
1077 fprintf(ctxt->output, "DOCUMENT == NULL !\n");
1078 return;
1079 }
1080 xmlCtxtDumpDocumentHead(ctxt, doc);
1081 if (((doc->type == XML_DOCUMENT_NODE) ||
1082 (doc->type == XML_HTML_DOCUMENT_NODE))
1083 && (doc->children != NULL)) {
1084 ctxt->depth++;
1085 xmlCtxtDumpNodeList(ctxt, doc->children);
1086 ctxt->depth--;
1087 }
1088}
1089
1090static void
1091xmlCtxtDumpEntityCallback(xmlEntityPtr cur, xmlDebugCtxtPtr ctxt)
1092{
1093 if (cur == NULL) {
1094 if (!ctxt->check)
1095 fprintf(ctxt->output, "Entity is NULL");
1096 return;
1097 }
1098 if (!ctxt->check) {
1099 fprintf(ctxt->output, "%s : ", (char *) cur->name);
1100 switch (cur->etype) {
1101 case XML_INTERNAL_GENERAL_ENTITY:
1102 fprintf(ctxt->output, "INTERNAL GENERAL, ");
1103 break;
1104 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1105 fprintf(ctxt->output, "EXTERNAL PARSED, ");
1106 break;
1107 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1108 fprintf(ctxt->output, "EXTERNAL UNPARSED, ");
1109 break;
1110 case XML_INTERNAL_PARAMETER_ENTITY:
1111 fprintf(ctxt->output, "INTERNAL PARAMETER, ");
1112 break;
1113 case XML_EXTERNAL_PARAMETER_ENTITY:
1114 fprintf(ctxt->output, "EXTERNAL PARAMETER, ");
1115 break;
1116 default:
Daniel Veillard8de5c0b2004-10-07 13:14:19 +00001117 xmlDebugErr2(ctxt, XML_CHECK_ENTITY_TYPE,
1118 "Unknown entity type %d\n", cur->etype);
Daniel Veillard22cdb842004-10-04 14:09:17 +00001119 }
1120 if (cur->ExternalID != NULL)
1121 fprintf(ctxt->output, "ID \"%s\"", (char *) cur->ExternalID);
1122 if (cur->SystemID != NULL)
1123 fprintf(ctxt->output, "SYSTEM \"%s\"", (char *) cur->SystemID);
1124 if (cur->orig != NULL)
1125 fprintf(ctxt->output, "\n orig \"%s\"", (char *) cur->orig);
1126 if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL))
1127 fprintf(ctxt->output, "\n content \"%s\"",
1128 (char *) cur->content);
1129 fprintf(ctxt->output, "\n");
1130 }
1131}
1132
1133/**
1134 * xmlCtxtDumpEntities:
1135 * @output: the FILE * for the output
1136 * @doc: the document
1137 *
1138 * Dumps debug information for all the entities in use by the document
1139 */
1140static void
1141xmlCtxtDumpEntities(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1142{
Daniel Veillard8de5c0b2004-10-07 13:14:19 +00001143 xmlCtxtDumpDocHead(ctxt, doc);
Daniel Veillard22cdb842004-10-04 14:09:17 +00001144 if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
1145 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1146 doc->intSubset->entities;
1147
1148 if (!ctxt->check)
1149 fprintf(ctxt->output, "Entities in internal subset\n");
1150 xmlHashScan(table, (xmlHashScanner) xmlCtxtDumpEntityCallback,
1151 ctxt);
1152 } else
1153 fprintf(ctxt->output, "No entities in internal subset\n");
1154 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
1155 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1156 doc->extSubset->entities;
1157
1158 if (!ctxt->check)
1159 fprintf(ctxt->output, "Entities in external subset\n");
1160 xmlHashScan(table, (xmlHashScanner) xmlCtxtDumpEntityCallback,
1161 ctxt);
1162 } else if (!ctxt->check)
1163 fprintf(ctxt->output, "No entities in external subset\n");
1164}
1165
1166/**
1167 * xmlCtxtDumpDTD:
1168 * @output: the FILE * for the output
1169 * @dtd: the DTD
1170 *
1171 * Dumps debug information for the DTD
1172 */
1173static void
1174xmlCtxtDumpDTD(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd)
1175{
1176 if (dtd == NULL) {
1177 if (!ctxt->check)
1178 fprintf(ctxt->output, "DTD is NULL\n");
1179 return;
1180 }
Daniel Veillard8de5c0b2004-10-07 13:14:19 +00001181 xmlCtxtDumpDtdNode(ctxt, dtd);
Daniel Veillard22cdb842004-10-04 14:09:17 +00001182 if (dtd->children == NULL)
1183 fprintf(ctxt->output, " DTD is empty\n");
1184 else {
1185 ctxt->depth++;
1186 xmlCtxtDumpNodeList(ctxt, dtd->children);
1187 ctxt->depth--;
1188 }
1189}
Daniel Veillard8de5c0b2004-10-07 13:14:19 +00001190
Daniel Veillard22cdb842004-10-04 14:09:17 +00001191/************************************************************************
1192 * *
Daniel Veillard8de5c0b2004-10-07 13:14:19 +00001193 * Public entry points for dump *
Daniel Veillard22cdb842004-10-04 14:09:17 +00001194 * *
1195 ************************************************************************/
1196
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001197/**
1198 * xmlDebugDumpString:
1199 * @output: the FILE * for the output
1200 * @str: the string
1201 *
1202 * Dumps informations about the string, shorten it if necessary
1203 */
1204void
1205xmlDebugDumpString(FILE * output, const xmlChar * str)
1206{
Owen Taylor3473f882001-02-23 17:55:21 +00001207 int i;
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001208
Daniel Veillard7db38712002-02-07 16:39:11 +00001209 if (output == NULL)
1210 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +00001211 if (str == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001212 fprintf(output, "(NULL)");
1213 return;
Owen Taylor3473f882001-02-23 17:55:21 +00001214 }
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001215 for (i = 0; i < 40; i++)
1216 if (str[i] == 0)
1217 return;
William M. Brack76e95df2003-10-18 16:20:14 +00001218 else if (IS_BLANK_CH(str[i]))
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001219 fputc(' ', output);
1220 else if (str[i] >= 0x80)
1221 fprintf(output, "#%X", str[i]);
1222 else
1223 fputc(str[i], output);
Owen Taylor3473f882001-02-23 17:55:21 +00001224 fprintf(output, "...");
1225}
1226
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001227/**
1228 * xmlDebugDumpAttr:
1229 * @output: the FILE * for the output
1230 * @attr: the attribute
1231 * @depth: the indentation level.
1232 *
1233 * Dumps debug information for the attribute
1234 */
1235void
1236xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
Daniel Veillard22cdb842004-10-04 14:09:17 +00001237 xmlDebugCtxt ctxt;
Owen Taylor3473f882001-02-23 17:55:21 +00001238
Daniel Veillard22cdb842004-10-04 14:09:17 +00001239 xmlCtxtDumpInitCtxt(&ctxt);
1240 ctxt.output = output;
1241 ctxt.depth = depth;
1242 xmlCtxtDumpAttr(&ctxt, attr);
Daniel Veillard76821142004-10-09 20:39:04 +00001243 xmlCtxtDumpCleanCtxt(&ctxt);
Daniel Veillard22cdb842004-10-04 14:09:17 +00001244}
Owen Taylor3473f882001-02-23 17:55:21 +00001245
Owen Taylor3473f882001-02-23 17:55:21 +00001246
Daniel Veillard22cdb842004-10-04 14:09:17 +00001247/**
1248 * xmlDebugDumpEntities:
1249 * @output: the FILE * for the output
1250 * @doc: the document
1251 *
1252 * Dumps debug information for all the entities in use by the document
1253 */
1254void
1255xmlDebugDumpEntities(FILE * output, xmlDocPtr doc)
1256{
1257 xmlDebugCtxt ctxt;
1258
1259 xmlCtxtDumpInitCtxt(&ctxt);
1260 ctxt.output = output;
1261 xmlCtxtDumpEntities(&ctxt, doc);
Daniel Veillard76821142004-10-09 20:39:04 +00001262 xmlCtxtDumpCleanCtxt(&ctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001263}
1264
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001265/**
1266 * xmlDebugDumpAttrList:
1267 * @output: the FILE * for the output
1268 * @attr: the attribute list
1269 * @depth: the indentation level.
1270 *
1271 * Dumps debug information for the attribute list
1272 */
1273void
1274xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth)
1275{
Daniel Veillard22cdb842004-10-04 14:09:17 +00001276 xmlDebugCtxt ctxt;
1277
1278 xmlCtxtDumpInitCtxt(&ctxt);
1279 ctxt.output = output;
1280 ctxt.depth = depth;
1281 xmlCtxtDumpAttrList(&ctxt, attr);
Daniel Veillard76821142004-10-09 20:39:04 +00001282 xmlCtxtDumpCleanCtxt(&ctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001283}
1284
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001285/**
1286 * xmlDebugDumpOneNode:
1287 * @output: the FILE * for the output
1288 * @node: the node
1289 * @depth: the indentation level.
1290 *
1291 * Dumps debug information for the element node, it is not recursive
1292 */
1293void
1294xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth)
1295{
Daniel Veillard22cdb842004-10-04 14:09:17 +00001296 xmlDebugCtxt ctxt;
Owen Taylor3473f882001-02-23 17:55:21 +00001297
Daniel Veillard22cdb842004-10-04 14:09:17 +00001298 xmlCtxtDumpInitCtxt(&ctxt);
1299 ctxt.output = output;
1300 ctxt.depth = depth;
1301 xmlCtxtDumpOneNode(&ctxt, node);
Daniel Veillard76821142004-10-09 20:39:04 +00001302 xmlCtxtDumpCleanCtxt(&ctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001303}
1304
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001305/**
1306 * xmlDebugDumpNode:
1307 * @output: the FILE * for the output
1308 * @node: the node
1309 * @depth: the indentation level.
1310 *
1311 * Dumps debug information for the element node, it is recursive
1312 */
1313void
1314xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth)
1315{
Daniel Veillard22cdb842004-10-04 14:09:17 +00001316 xmlDebugCtxt ctxt;
1317
Daniel Veillard7db38712002-02-07 16:39:11 +00001318 if (output == NULL)
1319 output = stdout;
Daniel Veillard22cdb842004-10-04 14:09:17 +00001320 xmlCtxtDumpInitCtxt(&ctxt);
1321 ctxt.output = output;
1322 ctxt.depth = depth;
1323 xmlCtxtDumpNode(&ctxt, node);
Daniel Veillard76821142004-10-09 20:39:04 +00001324 xmlCtxtDumpCleanCtxt(&ctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001325}
1326
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001327/**
1328 * xmlDebugDumpNodeList:
1329 * @output: the FILE * for the output
1330 * @node: the node list
1331 * @depth: the indentation level.
1332 *
1333 * Dumps debug information for the list of element node, it is recursive
1334 */
1335void
1336xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth)
1337{
Daniel Veillard22cdb842004-10-04 14:09:17 +00001338 xmlDebugCtxt ctxt;
1339
Daniel Veillard7db38712002-02-07 16:39:11 +00001340 if (output == NULL)
1341 output = stdout;
Daniel Veillard22cdb842004-10-04 14:09:17 +00001342 xmlCtxtDumpInitCtxt(&ctxt);
1343 ctxt.output = output;
1344 ctxt.depth = depth;
1345 xmlCtxtDumpNodeList(&ctxt, node);
Daniel Veillard76821142004-10-09 20:39:04 +00001346 xmlCtxtDumpCleanCtxt(&ctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001347}
1348
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001349/**
1350 * xmlDebugDumpDocumentHead:
1351 * @output: the FILE * for the output
1352 * @doc: the document
1353 *
1354 * Dumps debug information cncerning the document, not recursive
1355 */
1356void
1357xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc)
1358{
Daniel Veillard22cdb842004-10-04 14:09:17 +00001359 xmlDebugCtxt ctxt;
Owen Taylor3473f882001-02-23 17:55:21 +00001360
Daniel Veillard22cdb842004-10-04 14:09:17 +00001361 if (output == NULL)
1362 output = stdout;
1363 xmlCtxtDumpInitCtxt(&ctxt);
1364 ctxt.output = output;
1365 xmlCtxtDumpDocumentHead(&ctxt, doc);
Daniel Veillard76821142004-10-09 20:39:04 +00001366 xmlCtxtDumpCleanCtxt(&ctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001367}
1368
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001369/**
1370 * xmlDebugDumpDocument:
1371 * @output: the FILE * for the output
1372 * @doc: the document
1373 *
1374 * Dumps debug information for the document, it's recursive
1375 */
1376void
1377xmlDebugDumpDocument(FILE * output, xmlDocPtr doc)
1378{
Daniel Veillard22cdb842004-10-04 14:09:17 +00001379 xmlDebugCtxt ctxt;
1380
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001381 if (output == NULL)
Daniel Veillard22cdb842004-10-04 14:09:17 +00001382 output = stdout;
1383 xmlCtxtDumpInitCtxt(&ctxt);
1384 ctxt.output = output;
1385 xmlCtxtDumpDocument(&ctxt, doc);
Daniel Veillard76821142004-10-09 20:39:04 +00001386 xmlCtxtDumpCleanCtxt(&ctxt);
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001387}
Owen Taylor3473f882001-02-23 17:55:21 +00001388
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001389/**
1390 * xmlDebugDumpDTD:
1391 * @output: the FILE * for the output
1392 * @dtd: the DTD
1393 *
1394 * Dumps debug information for the DTD
1395 */
1396void
1397xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd)
1398{
Daniel Veillard22cdb842004-10-04 14:09:17 +00001399 xmlDebugCtxt ctxt;
1400
Daniel Veillard7db38712002-02-07 16:39:11 +00001401 if (output == NULL)
1402 output = stdout;
Daniel Veillard22cdb842004-10-04 14:09:17 +00001403 xmlCtxtDumpInitCtxt(&ctxt);
1404 ctxt.output = output;
1405 xmlCtxtDumpDTD(&ctxt, dtd);
Daniel Veillard76821142004-10-09 20:39:04 +00001406 xmlCtxtDumpCleanCtxt(&ctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001407}
1408
Daniel Veillard22cdb842004-10-04 14:09:17 +00001409/************************************************************************
1410 * *
Daniel Veillard8de5c0b2004-10-07 13:14:19 +00001411 * Public entry points for checkings *
1412 * *
1413 ************************************************************************/
1414
1415/**
1416 * xmlDebugCheckDocument:
1417 * @output: the FILE * for the output
1418 * @doc: the document
1419 *
1420 * Check the document for potential content problems, and output
1421 * the errors to @output
1422 *
1423 * Returns the number of errors found
1424 */
1425int
1426xmlDebugCheckDocument(FILE * output, xmlDocPtr doc)
1427{
1428 xmlDebugCtxt ctxt;
1429
1430 if (output == NULL)
1431 output = stdout;
1432 xmlCtxtDumpInitCtxt(&ctxt);
1433 ctxt.output = output;
1434 ctxt.check = 1;
1435 xmlCtxtDumpDocument(&ctxt, doc);
Daniel Veillard76821142004-10-09 20:39:04 +00001436 xmlCtxtDumpCleanCtxt(&ctxt);
Daniel Veillard8de5c0b2004-10-07 13:14:19 +00001437 return(ctxt.errors);
1438}
1439
1440/************************************************************************
1441 * *
Daniel Veillard22cdb842004-10-04 14:09:17 +00001442 * Helpers for Shell *
1443 * *
1444 ************************************************************************/
Owen Taylor3473f882001-02-23 17:55:21 +00001445
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001446/**
1447 * xmlLsCountNode:
1448 * @node: the node to count
1449 *
1450 * Count the children of @node.
1451 *
1452 * Returns the number of children of @node.
1453 */
1454int
1455xmlLsCountNode(xmlNodePtr node) {
Owen Taylor3473f882001-02-23 17:55:21 +00001456 int ret = 0;
1457 xmlNodePtr list = NULL;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001458
1459 if (node == NULL)
1460 return(0);
Owen Taylor3473f882001-02-23 17:55:21 +00001461
1462 switch (node->type) {
1463 case XML_ELEMENT_NODE:
1464 list = node->children;
1465 break;
1466 case XML_DOCUMENT_NODE:
1467 case XML_HTML_DOCUMENT_NODE:
Daniel Veillardeae522a2001-04-23 13:41:34 +00001468#ifdef LIBXML_DOCB_ENABLED
1469 case XML_DOCB_DOCUMENT_NODE:
Owen Taylor3473f882001-02-23 17:55:21 +00001470#endif
1471 list = ((xmlDocPtr) node)->children;
1472 break;
1473 case XML_ATTRIBUTE_NODE:
1474 list = ((xmlAttrPtr) node)->children;
1475 break;
1476 case XML_TEXT_NODE:
1477 case XML_CDATA_SECTION_NODE:
1478 case XML_PI_NODE:
1479 case XML_COMMENT_NODE:
1480 if (node->content != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001481 ret = xmlStrlen(node->content);
Owen Taylor3473f882001-02-23 17:55:21 +00001482 }
1483 break;
1484 case XML_ENTITY_REF_NODE:
1485 case XML_DOCUMENT_TYPE_NODE:
1486 case XML_ENTITY_NODE:
1487 case XML_DOCUMENT_FRAG_NODE:
1488 case XML_NOTATION_NODE:
1489 case XML_DTD_NODE:
1490 case XML_ELEMENT_DECL:
1491 case XML_ATTRIBUTE_DECL:
1492 case XML_ENTITY_DECL:
1493 case XML_NAMESPACE_DECL:
1494 case XML_XINCLUDE_START:
1495 case XML_XINCLUDE_END:
1496 ret = 1;
1497 break;
1498 }
1499 for (;list != NULL;ret++)
1500 list = list->next;
1501 return(ret);
1502}
1503
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001504/**
1505 * xmlLsOneNode:
1506 * @output: the FILE * for the output
1507 * @node: the node to dump
1508 *
1509 * Dump to @output the type and name of @node.
1510 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001511void
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001512xmlLsOneNode(FILE *output, xmlNodePtr node) {
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001513 if (node == NULL) {
1514 fprintf(output, "NULL\n");
1515 return;
1516 }
Owen Taylor3473f882001-02-23 17:55:21 +00001517 switch (node->type) {
1518 case XML_ELEMENT_NODE:
1519 fprintf(output, "-");
1520 break;
1521 case XML_ATTRIBUTE_NODE:
1522 fprintf(output, "a");
1523 break;
1524 case XML_TEXT_NODE:
1525 fprintf(output, "t");
1526 break;
1527 case XML_CDATA_SECTION_NODE:
Daniel Veillard75be0132002-03-13 10:03:35 +00001528 fprintf(output, "C");
Owen Taylor3473f882001-02-23 17:55:21 +00001529 break;
1530 case XML_ENTITY_REF_NODE:
1531 fprintf(output, "e");
1532 break;
1533 case XML_ENTITY_NODE:
1534 fprintf(output, "E");
1535 break;
1536 case XML_PI_NODE:
1537 fprintf(output, "p");
1538 break;
1539 case XML_COMMENT_NODE:
1540 fprintf(output, "c");
1541 break;
1542 case XML_DOCUMENT_NODE:
1543 fprintf(output, "d");
1544 break;
1545 case XML_HTML_DOCUMENT_NODE:
1546 fprintf(output, "h");
1547 break;
1548 case XML_DOCUMENT_TYPE_NODE:
1549 fprintf(output, "T");
1550 break;
1551 case XML_DOCUMENT_FRAG_NODE:
1552 fprintf(output, "F");
1553 break;
1554 case XML_NOTATION_NODE:
1555 fprintf(output, "N");
1556 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001557 case XML_NAMESPACE_DECL:
1558 fprintf(output, "n");
1559 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001560 default:
1561 fprintf(output, "?");
1562 }
Daniel Veillarde6a55192002-01-14 17:11:53 +00001563 if (node->type != XML_NAMESPACE_DECL) {
1564 if (node->properties != NULL)
1565 fprintf(output, "a");
1566 else
1567 fprintf(output, "-");
1568 if (node->nsDef != NULL)
1569 fprintf(output, "n");
1570 else
1571 fprintf(output, "-");
1572 }
Owen Taylor3473f882001-02-23 17:55:21 +00001573
1574 fprintf(output, " %8d ", xmlLsCountNode(node));
1575
1576 switch (node->type) {
1577 case XML_ELEMENT_NODE:
1578 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001579 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001580 break;
1581 case XML_ATTRIBUTE_NODE:
1582 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001583 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001584 break;
1585 case XML_TEXT_NODE:
1586 if (node->content != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001587 xmlDebugDumpString(output, node->content);
Owen Taylor3473f882001-02-23 17:55:21 +00001588 }
1589 break;
1590 case XML_CDATA_SECTION_NODE:
1591 break;
1592 case XML_ENTITY_REF_NODE:
1593 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001594 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001595 break;
1596 case XML_ENTITY_NODE:
1597 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001598 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001599 break;
1600 case XML_PI_NODE:
1601 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001602 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001603 break;
1604 case XML_COMMENT_NODE:
1605 break;
1606 case XML_DOCUMENT_NODE:
1607 break;
1608 case XML_HTML_DOCUMENT_NODE:
1609 break;
1610 case XML_DOCUMENT_TYPE_NODE:
1611 break;
1612 case XML_DOCUMENT_FRAG_NODE:
1613 break;
1614 case XML_NOTATION_NODE:
1615 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001616 case XML_NAMESPACE_DECL: {
1617 xmlNsPtr ns = (xmlNsPtr) node;
1618
1619 if (ns->prefix == NULL)
William M. Brack13dfa872004-09-18 04:52:08 +00001620 fprintf(output, "default -> %s", (char *)ns->href);
Daniel Veillarde6a55192002-01-14 17:11:53 +00001621 else
William M. Brack13dfa872004-09-18 04:52:08 +00001622 fprintf(output, "%s -> %s", (char *)ns->prefix,
1623 (char *)ns->href);
Daniel Veillarde6a55192002-01-14 17:11:53 +00001624 break;
1625 }
Owen Taylor3473f882001-02-23 17:55:21 +00001626 default:
1627 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001628 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001629 }
1630 fprintf(output, "\n");
1631}
1632
Daniel Veillard78d12092001-10-11 09:12:24 +00001633/**
1634 * xmlBoolToText:
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001635 * @boolval: a bool to turn into text
Daniel Veillard78d12092001-10-11 09:12:24 +00001636 *
1637 * Convenient way to turn bool into text
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001638 *
1639 * Returns a pointer to either "True" or "False"
1640 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001641const char *
Daniel Veillardebd38c52001-11-01 08:38:12 +00001642xmlBoolToText(int boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001643{
Daniel Veillardebd38c52001-11-01 08:38:12 +00001644 if (boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001645 return("True");
1646 else
1647 return("False");
1648}
1649
Owen Taylor3473f882001-02-23 17:55:21 +00001650/****************************************************************
1651 * *
1652 * The XML shell related functions *
1653 * *
1654 ****************************************************************/
1655
Daniel Veillard78d12092001-10-11 09:12:24 +00001656
1657
Owen Taylor3473f882001-02-23 17:55:21 +00001658/*
1659 * TODO: Improvement/cleanups for the XML shell
1660 * - allow to shell out an editor on a subpart
1661 * - cleanup function registrations (with help) and calling
1662 * - provide registration routines
1663 */
1664
1665/**
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001666 * xmlShellPrintXPathError:
Daniel Veillard78d12092001-10-11 09:12:24 +00001667 * @errorType: valid xpath error id
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001668 * @arg: the argument that cause xpath to fail
Daniel Veillard78d12092001-10-11 09:12:24 +00001669 *
1670 * Print the xpath error to libxml default error channel
1671 */
1672void
1673xmlShellPrintXPathError(int errorType, const char *arg)
1674{
1675 const char *default_arg = "Result";
1676
1677 if (!arg)
1678 arg = default_arg;
1679
1680 switch (errorType) {
1681 case XPATH_UNDEFINED:
1682 xmlGenericError(xmlGenericErrorContext,
1683 "%s: no such node\n", arg);
1684 break;
1685
1686 case XPATH_BOOLEAN:
1687 xmlGenericError(xmlGenericErrorContext,
1688 "%s is a Boolean\n", arg);
1689 break;
1690 case XPATH_NUMBER:
1691 xmlGenericError(xmlGenericErrorContext,
1692 "%s is a number\n", arg);
1693 break;
1694 case XPATH_STRING:
1695 xmlGenericError(xmlGenericErrorContext,
1696 "%s is a string\n", arg);
1697 break;
1698 case XPATH_POINT:
1699 xmlGenericError(xmlGenericErrorContext,
1700 "%s is a point\n", arg);
1701 break;
1702 case XPATH_RANGE:
1703 xmlGenericError(xmlGenericErrorContext,
1704 "%s is a range\n", arg);
1705 break;
1706 case XPATH_LOCATIONSET:
1707 xmlGenericError(xmlGenericErrorContext,
1708 "%s is a range\n", arg);
1709 break;
1710 case XPATH_USERS:
1711 xmlGenericError(xmlGenericErrorContext,
1712 "%s is user-defined\n", arg);
1713 break;
1714 case XPATH_XSLT_TREE:
1715 xmlGenericError(xmlGenericErrorContext,
1716 "%s is an XSLT value tree\n", arg);
1717 break;
1718 }
1719 xmlGenericError(xmlGenericErrorContext,
1720 "Try casting the result string function (xpath builtin)\n",
1721 arg);
1722}
1723
1724
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001725#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001726/**
Daniel Veillard321be0c2002-10-08 21:26:42 +00001727 * xmlShellPrintNodeCtxt:
1728 * @ctxt : a non-null shell context
1729 * @node : a non-null node to print to the output FILE
Daniel Veillard78d12092001-10-11 09:12:24 +00001730 *
Daniel Veillard321be0c2002-10-08 21:26:42 +00001731 * Print node to the output FILE
1732 */
1733static void
1734xmlShellPrintNodeCtxt(xmlShellCtxtPtr ctxt,xmlNodePtr node)
1735{
Daniel Veillard01992e02002-10-09 10:20:30 +00001736 FILE *fp;
1737
1738 if (!node)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001739 return;
Daniel Veillard01992e02002-10-09 10:20:30 +00001740 if (ctxt == NULL)
1741 fp = stdout;
1742 else
1743 fp = ctxt->output;
Daniel Veillard321be0c2002-10-08 21:26:42 +00001744
1745 if (node->type == XML_DOCUMENT_NODE)
Daniel Veillard01992e02002-10-09 10:20:30 +00001746 xmlDocDump(fp, (xmlDocPtr) node);
Daniel Veillard321be0c2002-10-08 21:26:42 +00001747 else if (node->type == XML_ATTRIBUTE_NODE)
Daniel Veillard01992e02002-10-09 10:20:30 +00001748 xmlDebugDumpAttrList(fp, (xmlAttrPtr) node, 0);
Daniel Veillard321be0c2002-10-08 21:26:42 +00001749 else
Daniel Veillard01992e02002-10-09 10:20:30 +00001750 xmlElemDump(fp, node->doc, node);
Daniel Veillard321be0c2002-10-08 21:26:42 +00001751
Daniel Veillard01992e02002-10-09 10:20:30 +00001752 fprintf(fp, "\n");
Daniel Veillard321be0c2002-10-08 21:26:42 +00001753}
1754
1755/**
1756 * xmlShellPrintNode:
1757 * @node : a non-null node to print to the output FILE
1758 *
1759 * Print node to the output FILE
Daniel Veillard78d12092001-10-11 09:12:24 +00001760 */
1761void
1762xmlShellPrintNode(xmlNodePtr node)
1763{
Daniel Veillard321be0c2002-10-08 21:26:42 +00001764 xmlShellPrintNodeCtxt(NULL, node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001765}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001766#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001767
Daniel Veillard78d12092001-10-11 09:12:24 +00001768/**
Daniel Veillard321be0c2002-10-08 21:26:42 +00001769 * xmlShellPrintXPathResultCtxt:
1770 * @ctxt: a valid shell context
Daniel Veillard9d06d302002-01-22 18:15:52 +00001771 * @list: a valid result generated by an xpath evaluation
Daniel Veillard78d12092001-10-11 09:12:24 +00001772 *
Daniel Veillard321be0c2002-10-08 21:26:42 +00001773 * Prints result to the output FILE
Daniel Veillard78d12092001-10-11 09:12:24 +00001774 */
Daniel Veillard321be0c2002-10-08 21:26:42 +00001775static void
1776xmlShellPrintXPathResultCtxt(xmlShellCtxtPtr ctxt,xmlXPathObjectPtr list)
Daniel Veillard78d12092001-10-11 09:12:24 +00001777{
Daniel Veillard321be0c2002-10-08 21:26:42 +00001778 if (!ctxt)
1779 return;
Daniel Veillard78d12092001-10-11 09:12:24 +00001780
1781 if (list != NULL) {
1782 switch (list->type) {
1783 case XPATH_NODESET:{
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001784#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001785 int indx;
1786
1787 if (list->nodesetval) {
1788 for (indx = 0; indx < list->nodesetval->nodeNr;
1789 indx++) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001790 xmlShellPrintNodeCtxt(ctxt,
1791 list->nodesetval->nodeTab[indx]);
Daniel Veillard78d12092001-10-11 09:12:24 +00001792 }
1793 } else {
1794 xmlGenericError(xmlGenericErrorContext,
1795 "Empty node set\n");
1796 }
1797 break;
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001798#else
1799 xmlGenericError(xmlGenericErrorContext,
1800 "Node set\n");
1801#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001802 }
1803 case XPATH_BOOLEAN:
1804 xmlGenericError(xmlGenericErrorContext,
1805 "Is a Boolean:%s\n",
1806 xmlBoolToText(list->boolval));
1807 break;
1808 case XPATH_NUMBER:
1809 xmlGenericError(xmlGenericErrorContext,
1810 "Is a number:%0g\n", list->floatval);
1811 break;
1812 case XPATH_STRING:
1813 xmlGenericError(xmlGenericErrorContext,
1814 "Is a string:%s\n", list->stringval);
1815 break;
1816
1817 default:
1818 xmlShellPrintXPathError(list->type, NULL);
1819 }
1820 }
1821}
1822
1823/**
Daniel Veillard321be0c2002-10-08 21:26:42 +00001824 * xmlShellPrintXPathResult:
1825 * @list: a valid result generated by an xpath evaluation
1826 *
1827 * Prints result to the output FILE
1828 */
1829void
1830xmlShellPrintXPathResult(xmlXPathObjectPtr list)
1831{
1832 xmlShellPrintXPathResultCtxt(NULL, list);
1833}
1834
1835/**
Owen Taylor3473f882001-02-23 17:55:21 +00001836 * xmlShellList:
1837 * @ctxt: the shell context
1838 * @arg: unused
1839 * @node: a node
1840 * @node2: unused
1841 *
1842 * Implements the XML shell function "ls"
1843 * Does an Unix like listing of the given node (like a directory)
1844 *
1845 * Returns 0
1846 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001847int
Daniel Veillard321be0c2002-10-08 21:26:42 +00001848xmlShellList(xmlShellCtxtPtr ctxt,
Daniel Veillard78d12092001-10-11 09:12:24 +00001849 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1850 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1851{
Owen Taylor3473f882001-02-23 17:55:21 +00001852 xmlNodePtr cur;
Daniel Veillard321be0c2002-10-08 21:26:42 +00001853 if (!ctxt)
1854 return (0);
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001855 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001856 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001857 return (0);
1858 }
Owen Taylor3473f882001-02-23 17:55:21 +00001859 if ((node->type == XML_DOCUMENT_NODE) ||
1860 (node->type == XML_HTML_DOCUMENT_NODE)) {
1861 cur = ((xmlDocPtr) node)->children;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001862 } else if (node->type == XML_NAMESPACE_DECL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001863 xmlLsOneNode(ctxt->output, node);
Daniel Veillarde6a55192002-01-14 17:11:53 +00001864 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001865 } else if (node->children != NULL) {
1866 cur = node->children;
1867 } else {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001868 xmlLsOneNode(ctxt->output, node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001869 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001870 }
1871 while (cur != NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001872 xmlLsOneNode(ctxt->output, cur);
Daniel Veillard78d12092001-10-11 09:12:24 +00001873 cur = cur->next;
Owen Taylor3473f882001-02-23 17:55:21 +00001874 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001875 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001876}
1877
1878/**
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001879 * xmlShellBase:
1880 * @ctxt: the shell context
1881 * @arg: unused
1882 * @node: a node
1883 * @node2: unused
1884 *
1885 * Implements the XML shell function "base"
1886 * dumps the current XML base of the node
1887 *
1888 * Returns 0
1889 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001890int
Daniel Veillard321be0c2002-10-08 21:26:42 +00001891xmlShellBase(xmlShellCtxtPtr ctxt,
Daniel Veillard78d12092001-10-11 09:12:24 +00001892 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1893 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1894{
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001895 xmlChar *base;
Daniel Veillard321be0c2002-10-08 21:26:42 +00001896 if (!ctxt)
1897 return 0;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001898 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001899 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001900 return (0);
1901 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001902
1903 base = xmlNodeGetBase(node->doc, node);
1904
1905 if (base == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001906 fprintf(ctxt->output, " No base found !!!\n");
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001907 } else {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001908 fprintf(ctxt->output, "%s\n", base);
Daniel Veillard78d12092001-10-11 09:12:24 +00001909 xmlFree(base);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001910 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001911 return (0);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001912}
1913
Daniel Veillardb34321c2004-03-04 17:09:47 +00001914#ifdef LIBXML_TREE_ENABLED
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001915/**
Daniel Veillardcfa0d812002-01-17 08:46:58 +00001916 * xmlShellSetBase:
1917 * @ctxt: the shell context
1918 * @arg: the new base
1919 * @node: a node
1920 * @node2: unused
1921 *
1922 * Implements the XML shell function "setbase"
1923 * change the current XML base of the node
1924 *
1925 * Returns 0
1926 */
1927static int
1928xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1929 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1930 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1931{
1932 xmlNodeSetBase(node, (xmlChar*) arg);
1933 return (0);
1934}
Daniel Veillard2156d432004-03-04 15:59:36 +00001935#endif
Daniel Veillardcfa0d812002-01-17 08:46:58 +00001936
Daniel Veillardbbaa9972004-06-16 14:08:33 +00001937#ifdef LIBXML_XPATH_ENABLED
1938/**
1939 * xmlShellRegisterNamespace:
1940 * @ctxt: the shell context
1941 * @arg: a string in prefix=nsuri format
1942 * @node: unused
1943 * @node2: unused
1944 *
1945 * Implements the XML shell function "setns"
1946 * register/unregister a prefix=namespace pair
1947 * on the XPath context
1948 *
1949 * Returns 0 on success and a negative value otherwise.
1950 */
1951static int
1952xmlShellRegisterNamespace(xmlShellCtxtPtr ctxt, char *arg,
1953 xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1954{
1955 xmlChar* nsListDup;
1956 xmlChar* prefix;
1957 xmlChar* href;
1958 xmlChar* next;
1959
1960 nsListDup = xmlStrdup((xmlChar *) arg);
1961 next = nsListDup;
1962 while(next != NULL) {
1963 /* skip spaces */
1964 /*while((*next) == ' ') next++;*/
1965 if((*next) == '\0') break;
1966
1967 /* find prefix */
1968 prefix = next;
1969 next = (xmlChar*)xmlStrchr(next, '=');
1970 if(next == NULL) {
1971 fprintf(ctxt->output, "setns: prefix=[nsuri] required\n");
1972 xmlFree(nsListDup);
1973 return(-1);
1974 }
1975 *(next++) = '\0';
1976
1977 /* find href */
1978 href = next;
1979 next = (xmlChar*)xmlStrchr(next, ' ');
1980 if(next != NULL) {
1981 *(next++) = '\0';
1982 }
1983
1984 /* do register namespace */
1985 if(xmlXPathRegisterNs(ctxt->pctxt, prefix, href) != 0) {
1986 fprintf(ctxt->output,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", prefix, href);
1987 xmlFree(nsListDup);
1988 return(-1);
1989 }
1990 }
1991
1992 xmlFree(nsListDup);
1993 return(0);
1994}
1995#endif
1996
Daniel Veillardcfa0d812002-01-17 08:46:58 +00001997/**
Daniel Veillard1e208222002-10-22 14:25:25 +00001998 * xmlShellGrep:
1999 * @ctxt: the shell context
2000 * @arg: the string or regular expression to find
2001 * @node: a node
2002 * @node2: unused
2003 *
2004 * Implements the XML shell function "grep"
2005 * dumps informations about the node (namespace, attributes, content).
2006 *
2007 * Returns 0
2008 */
Daniel Veillarde645e8c2002-10-22 17:35:37 +00002009static int
Daniel Veillard1e208222002-10-22 14:25:25 +00002010xmlShellGrep(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
2011 char *arg, xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2012{
2013 if (!ctxt)
2014 return (0);
2015 if (node == NULL)
2016 return (0);
2017 if (arg == NULL)
2018 return (0);
2019#ifdef LIBXML_REGEXP_ENABLED
2020 if ((xmlStrchr((xmlChar *) arg, '?')) ||
2021 (xmlStrchr((xmlChar *) arg, '*')) ||
2022 (xmlStrchr((xmlChar *) arg, '.')) ||
2023 (xmlStrchr((xmlChar *) arg, '['))) {
2024 }
2025#endif
2026 while (node != NULL) {
2027 if (node->type == XML_COMMENT_NODE) {
Daniel Veillarde645e8c2002-10-22 17:35:37 +00002028 if (xmlStrstr(node->content, (xmlChar *) arg)) {
Daniel Veillard1e208222002-10-22 14:25:25 +00002029
2030 fprintf(ctxt->output, "%s : ", xmlGetNodePath(node));
2031 xmlShellList(ctxt, NULL, node, NULL);
2032 }
2033 } else if (node->type == XML_TEXT_NODE) {
Daniel Veillarde645e8c2002-10-22 17:35:37 +00002034 if (xmlStrstr(node->content, (xmlChar *) arg)) {
Daniel Veillard1e208222002-10-22 14:25:25 +00002035
2036 fprintf(ctxt->output, "%s : ", xmlGetNodePath(node->parent));
Daniel Veillarde645e8c2002-10-22 17:35:37 +00002037 xmlShellList(ctxt, NULL, node->parent, NULL);
Daniel Veillard1e208222002-10-22 14:25:25 +00002038 }
2039 }
2040
2041 /*
2042 * Browse the full subtree, deep first
2043 */
2044
2045 if ((node->type == XML_DOCUMENT_NODE) ||
2046 (node->type == XML_HTML_DOCUMENT_NODE)) {
2047 node = ((xmlDocPtr) node)->children;
2048 } else if ((node->children != NULL)
2049 && (node->type != XML_ENTITY_REF_NODE)) {
2050 /* deep first */
2051 node = node->children;
2052 } else if (node->next != NULL) {
2053 /* then siblings */
2054 node = node->next;
2055 } else {
2056 /* go up to parents->next if needed */
2057 while (node != NULL) {
2058 if (node->parent != NULL) {
2059 node = node->parent;
2060 }
2061 if (node->next != NULL) {
2062 node = node->next;
2063 break;
2064 }
2065 if (node->parent == NULL) {
2066 node = NULL;
2067 break;
2068 }
2069 }
2070 }
2071 }
2072 return (0);
2073}
2074
2075/**
Owen Taylor3473f882001-02-23 17:55:21 +00002076 * xmlShellDir:
2077 * @ctxt: the shell context
2078 * @arg: unused
2079 * @node: a node
2080 * @node2: unused
2081 *
2082 * Implements the XML shell function "dir"
2083 * dumps informations about the node (namespace, attributes, content).
2084 *
2085 * Returns 0
2086 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002087int
2088xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
2089 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
2090 xmlNodePtr node2 ATTRIBUTE_UNUSED)
2091{
Daniel Veillard321be0c2002-10-08 21:26:42 +00002092 if (!ctxt)
2093 return (0);
Daniel Veillard5e926fa2002-01-22 21:44:25 +00002094 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002095 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00002096 return (0);
2097 }
Owen Taylor3473f882001-02-23 17:55:21 +00002098 if ((node->type == XML_DOCUMENT_NODE) ||
2099 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002100 xmlDebugDumpDocumentHead(ctxt->output, (xmlDocPtr) node);
Owen Taylor3473f882001-02-23 17:55:21 +00002101 } else if (node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002102 xmlDebugDumpAttr(ctxt->output, (xmlAttrPtr) node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00002103 } else {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002104 xmlDebugDumpOneNode(ctxt->output, node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00002105 }
Daniel Veillard78d12092001-10-11 09:12:24 +00002106 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002107}
2108
Daniel Veillard29b17482004-08-16 00:39:03 +00002109/**
2110 * xmlShellSetContent:
2111 * @ctxt: the shell context
2112 * @value: the content as a string
2113 * @node: a node
2114 * @node2: unused
2115 *
2116 * Implements the XML shell function "dir"
2117 * dumps informations about the node (namespace, attributes, content).
2118 *
2119 * Returns 0
2120 */
2121static int
2122xmlShellSetContent(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
2123 char *value, xmlNodePtr node,
2124 xmlNodePtr node2 ATTRIBUTE_UNUSED)
2125{
2126 xmlNodePtr results;
2127 xmlParserErrors ret;
2128
2129 if (!ctxt)
2130 return (0);
2131 if (node == NULL) {
2132 fprintf(ctxt->output, "NULL\n");
2133 return (0);
2134 }
2135 if (value == NULL) {
2136 fprintf(ctxt->output, "NULL\n");
2137 return (0);
2138 }
2139
2140 ret = xmlParseInNodeContext(node, value, strlen(value), 0, &results);
2141 if (ret == XML_ERR_OK) {
2142 if (node->children != NULL) {
2143 xmlFreeNodeList(node->children);
2144 node->children = NULL;
2145 node->last = NULL;
2146 }
2147 xmlAddChildList(node, results);
2148 } else {
2149 fprintf(ctxt->output, "failed to parse content\n");
2150 }
2151 return (0);
2152}
2153
Daniel Veillard522bc602004-02-21 11:53:09 +00002154#ifdef LIBXML_SCHEMAS_ENABLED
2155/**
2156 * xmlShellRNGValidate:
2157 * @ctxt: the shell context
2158 * @schemas: the path to the Relax-NG schemas
2159 * @node: a node
2160 * @node2: unused
2161 *
2162 * Implements the XML shell function "relaxng"
2163 * validating the instance against a Relax-NG schemas
2164 *
2165 * Returns 0
2166 */
2167static int
2168xmlShellRNGValidate(xmlShellCtxtPtr sctxt, char *schemas,
2169 xmlNodePtr node ATTRIBUTE_UNUSED,
2170 xmlNodePtr node2 ATTRIBUTE_UNUSED)
2171{
2172 xmlRelaxNGPtr relaxngschemas;
2173 xmlRelaxNGParserCtxtPtr ctxt;
2174 xmlRelaxNGValidCtxtPtr vctxt;
2175 int ret;
2176
2177 ctxt = xmlRelaxNGNewParserCtxt(schemas);
2178 xmlRelaxNGSetParserErrors(ctxt,
2179 (xmlRelaxNGValidityErrorFunc) fprintf,
2180 (xmlRelaxNGValidityWarningFunc) fprintf,
2181 stderr);
2182 relaxngschemas = xmlRelaxNGParse(ctxt);
2183 xmlRelaxNGFreeParserCtxt(ctxt);
2184 if (relaxngschemas == NULL) {
2185 xmlGenericError(xmlGenericErrorContext,
2186 "Relax-NG schema %s failed to compile\n", schemas);
2187 return(-1);
2188 }
2189 vctxt = xmlRelaxNGNewValidCtxt(relaxngschemas);
2190 xmlRelaxNGSetValidErrors(vctxt,
2191 (xmlRelaxNGValidityErrorFunc) fprintf,
2192 (xmlRelaxNGValidityWarningFunc) fprintf,
2193 stderr);
2194 ret = xmlRelaxNGValidateDoc(vctxt, sctxt->doc);
2195 if (ret == 0) {
2196 fprintf(stderr, "%s validates\n", sctxt->filename);
2197 } else if (ret > 0) {
2198 fprintf(stderr, "%s fails to validate\n", sctxt->filename);
2199 } else {
2200 fprintf(stderr, "%s validation generated an internal error\n",
2201 sctxt->filename);
2202 }
2203 xmlRelaxNGFreeValidCtxt(vctxt);
2204 if (relaxngschemas != NULL)
2205 xmlRelaxNGFree(relaxngschemas);
2206 return(0);
2207}
2208#endif
2209
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002210#ifdef LIBXML_OUTPUT_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00002211/**
2212 * xmlShellCat:
2213 * @ctxt: the shell context
2214 * @arg: unused
2215 * @node: a node
2216 * @node2: unused
2217 *
2218 * Implements the XML shell function "cat"
2219 * dumps the serialization node content (XML or HTML).
2220 *
2221 * Returns 0
2222 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002223int
2224xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
2225 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2226{
Daniel Veillard321be0c2002-10-08 21:26:42 +00002227 if (!ctxt)
2228 return (0);
Daniel Veillard5e926fa2002-01-22 21:44:25 +00002229 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002230 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00002231 return (0);
2232 }
Owen Taylor3473f882001-02-23 17:55:21 +00002233 if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
2234#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002235 if (node->type == XML_HTML_DOCUMENT_NODE)
Daniel Veillard321be0c2002-10-08 21:26:42 +00002236 htmlDocDump(ctxt->output, (htmlDocPtr) node);
Daniel Veillard78d12092001-10-11 09:12:24 +00002237 else
Daniel Veillard321be0c2002-10-08 21:26:42 +00002238 htmlNodeDumpFile(ctxt->output, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00002239#else
Daniel Veillard78d12092001-10-11 09:12:24 +00002240 if (node->type == XML_DOCUMENT_NODE)
Daniel Veillard321be0c2002-10-08 21:26:42 +00002241 xmlDocDump(ctxt->output, (xmlDocPtr) node);
Daniel Veillard78d12092001-10-11 09:12:24 +00002242 else
Daniel Veillard321be0c2002-10-08 21:26:42 +00002243 xmlElemDump(ctxt->output, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00002244#endif /* LIBXML_HTML_ENABLED */
2245 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00002246 if (node->type == XML_DOCUMENT_NODE)
Daniel Veillard321be0c2002-10-08 21:26:42 +00002247 xmlDocDump(ctxt->output, (xmlDocPtr) node);
Daniel Veillard78d12092001-10-11 09:12:24 +00002248 else
Daniel Veillard321be0c2002-10-08 21:26:42 +00002249 xmlElemDump(ctxt->output, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00002250 }
Daniel Veillard321be0c2002-10-08 21:26:42 +00002251 fprintf(ctxt->output, "\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00002252 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002253}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002254#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00002255
2256/**
2257 * xmlShellLoad:
2258 * @ctxt: the shell context
2259 * @filename: the file name
2260 * @node: unused
2261 * @node2: unused
2262 *
2263 * Implements the XML shell function "load"
2264 * loads a new document specified by the filename
2265 *
2266 * Returns 0 or -1 if loading failed
2267 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002268int
2269xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename,
2270 xmlNodePtr node ATTRIBUTE_UNUSED,
2271 xmlNodePtr node2 ATTRIBUTE_UNUSED)
2272{
Owen Taylor3473f882001-02-23 17:55:21 +00002273 xmlDocPtr doc;
2274 int html = 0;
2275
2276 if (ctxt->doc != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002277 html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
Owen Taylor3473f882001-02-23 17:55:21 +00002278
2279 if (html) {
2280#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002281 doc = htmlParseFile(filename, NULL);
2282#else
Daniel Veillard321be0c2002-10-08 21:26:42 +00002283 fprintf(ctxt->output, "HTML support not compiled in\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00002284 doc = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00002285#endif /* LIBXML_HTML_ENABLED */
2286 } else {
Daniel Veillardebe25d42004-03-25 09:35:49 +00002287 doc = xmlReadFile(filename,NULL,0);
Owen Taylor3473f882001-02-23 17:55:21 +00002288 }
2289 if (doc != NULL) {
2290 if (ctxt->loaded == 1) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002291 xmlFreeDoc(ctxt->doc);
2292 }
2293 ctxt->loaded = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00002294#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002295 xmlXPathFreeContext(ctxt->pctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00002296#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00002297 xmlFree(ctxt->filename);
2298 ctxt->doc = doc;
2299 ctxt->node = (xmlNodePtr) doc;
Owen Taylor3473f882001-02-23 17:55:21 +00002300#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002301 ctxt->pctxt = xmlXPathNewContext(doc);
Owen Taylor3473f882001-02-23 17:55:21 +00002302#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard85095e22003-04-23 13:56:44 +00002303 ctxt->filename = (char *) xmlCanonicPath((xmlChar *) filename);
Owen Taylor3473f882001-02-23 17:55:21 +00002304 } else
Daniel Veillard78d12092001-10-11 09:12:24 +00002305 return (-1);
2306 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002307}
2308
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002309#ifdef LIBXML_OUTPUT_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00002310/**
2311 * xmlShellWrite:
2312 * @ctxt: the shell context
2313 * @filename: the file name
2314 * @node: a node in the tree
2315 * @node2: unused
2316 *
2317 * Implements the XML shell function "write"
Daniel Veillardcbaf3992001-12-31 16:16:02 +00002318 * Write the current node to the filename, it saves the serialization
Owen Taylor3473f882001-02-23 17:55:21 +00002319 * of the subtree under the @node specified
2320 *
2321 * Returns 0 or -1 in case of error
2322 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002323int
Owen Taylor3473f882001-02-23 17:55:21 +00002324xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
Daniel Veillard78d12092001-10-11 09:12:24 +00002325 xmlNodePtr node2 ATTRIBUTE_UNUSED)
2326{
Owen Taylor3473f882001-02-23 17:55:21 +00002327 if (node == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002328 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002329 if ((filename == NULL) || (filename[0] == 0)) {
2330 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00002331 "Write command requires a filename argument\n");
2332 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002333 }
2334#ifdef W_OK
2335 if (access((char *) filename, W_OK)) {
2336 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00002337 "Cannot write to %s\n", filename);
2338 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002339 }
Daniel Veillard78d12092001-10-11 09:12:24 +00002340#endif
2341 switch (node->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00002342 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00002343 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
2344 xmlGenericError(xmlGenericErrorContext,
2345 "Failed to write to %s\n", filename);
2346 return (-1);
2347 }
2348 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002349 case XML_HTML_DOCUMENT_NODE:
2350#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002351 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
2352 xmlGenericError(xmlGenericErrorContext,
2353 "Failed to write to %s\n", filename);
2354 return (-1);
2355 }
Owen Taylor3473f882001-02-23 17:55:21 +00002356#else
Daniel Veillard78d12092001-10-11 09:12:24 +00002357 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
2358 xmlGenericError(xmlGenericErrorContext,
2359 "Failed to write to %s\n", filename);
2360 return (-1);
2361 }
Owen Taylor3473f882001-02-23 17:55:21 +00002362#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00002363 break;
2364 default:{
2365 FILE *f;
Owen Taylor3473f882001-02-23 17:55:21 +00002366
Daniel Veillard78d12092001-10-11 09:12:24 +00002367 f = fopen((char *) filename, "w");
2368 if (f == NULL) {
2369 xmlGenericError(xmlGenericErrorContext,
2370 "Failed to write to %s\n", filename);
2371 return (-1);
2372 }
2373 xmlElemDump(f, ctxt->doc, node);
2374 fclose(f);
2375 }
Owen Taylor3473f882001-02-23 17:55:21 +00002376 }
Daniel Veillard78d12092001-10-11 09:12:24 +00002377 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002378}
2379
2380/**
2381 * xmlShellSave:
2382 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00002383 * @filename: the file name (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00002384 * @node: unused
2385 * @node2: unused
2386 *
2387 * Implements the XML shell function "save"
2388 * Write the current document to the filename, or it's original name
2389 *
2390 * Returns 0 or -1 in case of error
2391 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002392int
2393xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
2394 xmlNodePtr node ATTRIBUTE_UNUSED,
2395 xmlNodePtr node2 ATTRIBUTE_UNUSED)
2396{
Owen Taylor3473f882001-02-23 17:55:21 +00002397 if (ctxt->doc == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002398 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002399 if ((filename == NULL) || (filename[0] == 0))
2400 filename = ctxt->filename;
2401#ifdef W_OK
2402 if (access((char *) filename, W_OK)) {
2403 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00002404 "Cannot save to %s\n", filename);
2405 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002406 }
2407#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00002408 switch (ctxt->doc->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00002409 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00002410 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
2411 xmlGenericError(xmlGenericErrorContext,
2412 "Failed to save to %s\n", filename);
2413 }
2414 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002415 case XML_HTML_DOCUMENT_NODE:
2416#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002417 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
2418 xmlGenericError(xmlGenericErrorContext,
2419 "Failed to save to %s\n", filename);
2420 }
Owen Taylor3473f882001-02-23 17:55:21 +00002421#else
Daniel Veillard78d12092001-10-11 09:12:24 +00002422 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
2423 xmlGenericError(xmlGenericErrorContext,
2424 "Failed to save to %s\n", filename);
2425 }
Owen Taylor3473f882001-02-23 17:55:21 +00002426#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00002427 break;
2428 default:
2429 xmlGenericError(xmlGenericErrorContext,
2430 "To save to subparts of a document use the 'write' command\n");
2431 return (-1);
2432
Owen Taylor3473f882001-02-23 17:55:21 +00002433 }
Daniel Veillard78d12092001-10-11 09:12:24 +00002434 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002435}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002436#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00002437
Daniel Veillardf54cd532004-02-25 11:52:31 +00002438#ifdef LIBXML_VALID_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00002439/**
2440 * xmlShellValidate:
2441 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00002442 * @dtd: the DTD URI (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00002443 * @node: unused
2444 * @node2: unused
2445 *
2446 * Implements the XML shell function "validate"
2447 * Validate the document, if a DTD path is provided, then the validation
2448 * is done against the given DTD.
2449 *
2450 * Returns 0 or -1 in case of error
2451 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002452int
2453xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd,
2454 xmlNodePtr node ATTRIBUTE_UNUSED,
2455 xmlNodePtr node2 ATTRIBUTE_UNUSED)
2456{
Owen Taylor3473f882001-02-23 17:55:21 +00002457 xmlValidCtxt vctxt;
2458 int res = -1;
2459
2460 vctxt.userData = stderr;
2461 vctxt.error = (xmlValidityErrorFunc) fprintf;
2462 vctxt.warning = (xmlValidityWarningFunc) fprintf;
2463
2464 if ((dtd == NULL) || (dtd[0] == 0)) {
2465 res = xmlValidateDocument(&vctxt, ctxt->doc);
2466 } else {
2467 xmlDtdPtr subset;
2468
Daniel Veillard78d12092001-10-11 09:12:24 +00002469 subset = xmlParseDTD(NULL, (xmlChar *) dtd);
2470 if (subset != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00002471 res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
2472
Daniel Veillard78d12092001-10-11 09:12:24 +00002473 xmlFreeDtd(subset);
2474 }
Owen Taylor3473f882001-02-23 17:55:21 +00002475 }
Daniel Veillard78d12092001-10-11 09:12:24 +00002476 return (res);
Owen Taylor3473f882001-02-23 17:55:21 +00002477}
Daniel Veillardf54cd532004-02-25 11:52:31 +00002478#endif /* LIBXML_VALID_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00002479
2480/**
2481 * xmlShellDu:
2482 * @ctxt: the shell context
2483 * @arg: unused
2484 * @tree: a node defining a subtree
2485 * @node2: unused
2486 *
2487 * Implements the XML shell function "du"
2488 * show the structure of the subtree under node @tree
2489 * If @tree is null, the command works on the current node.
2490 *
2491 * Returns 0 or -1 in case of error
2492 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002493int
Daniel Veillard321be0c2002-10-08 21:26:42 +00002494xmlShellDu(xmlShellCtxtPtr ctxt,
Daniel Veillard78d12092001-10-11 09:12:24 +00002495 char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree,
2496 xmlNodePtr node2 ATTRIBUTE_UNUSED)
2497{
Owen Taylor3473f882001-02-23 17:55:21 +00002498 xmlNodePtr node;
Daniel Veillard78d12092001-10-11 09:12:24 +00002499 int indent = 0, i;
Owen Taylor3473f882001-02-23 17:55:21 +00002500
Daniel Veillard321be0c2002-10-08 21:26:42 +00002501 if (!ctxt)
2502 return (-1);
2503
Daniel Veillard78d12092001-10-11 09:12:24 +00002504 if (tree == NULL)
2505 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002506 node = tree;
2507 while (node != NULL) {
2508 if ((node->type == XML_DOCUMENT_NODE) ||
2509 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002510 fprintf(ctxt->output, "/\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00002511 } else if (node->type == XML_ELEMENT_NODE) {
2512 for (i = 0; i < indent; i++)
Daniel Veillard321be0c2002-10-08 21:26:42 +00002513 fprintf(ctxt->output, " ");
2514 fprintf(ctxt->output, "%s\n", node->name);
Daniel Veillard78d12092001-10-11 09:12:24 +00002515 } else {
2516 }
Owen Taylor3473f882001-02-23 17:55:21 +00002517
Daniel Veillard78d12092001-10-11 09:12:24 +00002518 /*
2519 * Browse the full subtree, deep first
2520 */
Owen Taylor3473f882001-02-23 17:55:21 +00002521
2522 if ((node->type == XML_DOCUMENT_NODE) ||
2523 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002524 node = ((xmlDocPtr) node)->children;
2525 } else if ((node->children != NULL)
2526 && (node->type != XML_ENTITY_REF_NODE)) {
2527 /* deep first */
2528 node = node->children;
2529 indent++;
2530 } else if ((node != tree) && (node->next != NULL)) {
2531 /* then siblings */
2532 node = node->next;
2533 } else if (node != tree) {
2534 /* go up to parents->next if needed */
2535 while (node != tree) {
2536 if (node->parent != NULL) {
2537 node = node->parent;
2538 indent--;
2539 }
2540 if ((node != tree) && (node->next != NULL)) {
2541 node = node->next;
2542 break;
2543 }
2544 if (node->parent == NULL) {
2545 node = NULL;
2546 break;
2547 }
2548 if (node == tree) {
2549 node = NULL;
2550 break;
2551 }
2552 }
2553 /* exit condition */
2554 if (node == tree)
2555 node = NULL;
2556 } else
2557 node = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00002558 }
Daniel Veillard78d12092001-10-11 09:12:24 +00002559 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002560}
2561
2562/**
2563 * xmlShellPwd:
2564 * @ctxt: the shell context
2565 * @buffer: the output buffer
Daniel Veillard9d06d302002-01-22 18:15:52 +00002566 * @node: a node
Owen Taylor3473f882001-02-23 17:55:21 +00002567 * @node2: unused
2568 *
2569 * Implements the XML shell function "pwd"
2570 * Show the full path from the root to the node, if needed building
2571 * thumblers when similar elements exists at a given ancestor level.
2572 * The output is compatible with XPath commands.
2573 *
2574 * Returns 0 or -1 in case of error
2575 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002576int
2577xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
2578 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2579{
Daniel Veillardc6e013a2001-11-10 10:08:57 +00002580 xmlChar *path;
Owen Taylor3473f882001-02-23 17:55:21 +00002581
Daniel Veillard78d12092001-10-11 09:12:24 +00002582 if (node == NULL)
2583 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002584
Daniel Veillardc6e013a2001-11-10 10:08:57 +00002585 path = xmlGetNodePath(node);
2586 if (path == NULL)
2587 return (-1);
2588
2589 /*
2590 * This test prevents buffer overflow, because this routine
2591 * is only called by xmlShell, in which the second argument is
2592 * 500 chars long.
2593 * It is a dirty hack before a cleaner solution is found.
2594 * Documentation should mention that the second argument must
2595 * be at least 500 chars long, and could be stripped if too long.
2596 */
2597 snprintf(buffer, 499, "%s", path);
2598 buffer[499] = '0';
2599 xmlFree(path);
2600
Daniel Veillard78d12092001-10-11 09:12:24 +00002601 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002602}
2603
2604/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002605 * xmlShell:
Owen Taylor3473f882001-02-23 17:55:21 +00002606 * @doc: the initial document
2607 * @filename: the output buffer
2608 * @input: the line reading function
Daniel Veillard321be0c2002-10-08 21:26:42 +00002609 * @output: the output FILE*, defaults to stdout if NULL
Owen Taylor3473f882001-02-23 17:55:21 +00002610 *
2611 * Implements the XML shell
2612 * This allow to load, validate, view, modify and save a document
2613 * using a environment similar to a UNIX commandline.
2614 */
2615void
2616xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
Daniel Veillard78d12092001-10-11 09:12:24 +00002617 FILE * output)
2618{
Owen Taylor3473f882001-02-23 17:55:21 +00002619 char prompt[500] = "/ > ";
2620 char *cmdline = NULL, *cur;
2621 int nbargs;
2622 char command[100];
2623 char arg[400];
2624 int i;
2625 xmlShellCtxtPtr ctxt;
2626 xmlXPathObjectPtr list;
2627
2628 if (doc == NULL)
2629 return;
2630 if (filename == NULL)
2631 return;
2632 if (input == NULL)
2633 return;
2634 if (output == NULL)
Daniel Veillard321be0c2002-10-08 21:26:42 +00002635 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +00002636 ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
Daniel Veillard78d12092001-10-11 09:12:24 +00002637 if (ctxt == NULL)
Owen Taylor3473f882001-02-23 17:55:21 +00002638 return;
2639 ctxt->loaded = 0;
2640 ctxt->doc = doc;
2641 ctxt->input = input;
2642 ctxt->output = output;
2643 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
Daniel Veillard78d12092001-10-11 09:12:24 +00002644 ctxt->node = (xmlNodePtr) ctxt->doc;
Owen Taylor3473f882001-02-23 17:55:21 +00002645
2646#ifdef LIBXML_XPATH_ENABLED
2647 ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
2648 if (ctxt->pctxt == NULL) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002649 xmlFree(ctxt);
2650 return;
Owen Taylor3473f882001-02-23 17:55:21 +00002651 }
2652#endif /* LIBXML_XPATH_ENABLED */
2653 while (1) {
2654 if (ctxt->node == (xmlNodePtr) ctxt->doc)
Aleksey Sanin49cc9752002-06-14 17:07:10 +00002655 snprintf(prompt, sizeof(prompt), "%s > ", "/");
Daniel Veillard7a985a12003-07-06 17:57:42 +00002656 else if ((ctxt->node != NULL) && (ctxt->node->name))
Daniel Veillard78d12092001-10-11 09:12:24 +00002657 snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00002658 else
Aleksey Sanin49cc9752002-06-14 17:07:10 +00002659 snprintf(prompt, sizeof(prompt), "? > ");
Owen Taylor3473f882001-02-23 17:55:21 +00002660 prompt[sizeof(prompt) - 1] = 0;
2661
Daniel Veillard78d12092001-10-11 09:12:24 +00002662 /*
2663 * Get a new command line
2664 */
Owen Taylor3473f882001-02-23 17:55:21 +00002665 cmdline = ctxt->input(prompt);
Daniel Veillard78d12092001-10-11 09:12:24 +00002666 if (cmdline == NULL)
2667 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002668
Daniel Veillard78d12092001-10-11 09:12:24 +00002669 /*
2670 * Parse the command itself
2671 */
2672 cur = cmdline;
2673 nbargs = 0;
2674 while ((*cur == ' ') || (*cur == '\t'))
2675 cur++;
2676 i = 0;
2677 while ((*cur != ' ') && (*cur != '\t') &&
2678 (*cur != '\n') && (*cur != '\r')) {
2679 if (*cur == 0)
2680 break;
2681 command[i++] = *cur++;
2682 }
2683 command[i] = 0;
2684 if (i == 0)
2685 continue;
2686 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00002687
Daniel Veillard78d12092001-10-11 09:12:24 +00002688 /*
2689 * Parse the argument
2690 */
2691 while ((*cur == ' ') || (*cur == '\t'))
2692 cur++;
2693 i = 0;
2694 while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
2695 if (*cur == 0)
2696 break;
2697 arg[i++] = *cur++;
2698 }
2699 arg[i] = 0;
2700 if (i != 0)
2701 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00002702
Daniel Veillard78d12092001-10-11 09:12:24 +00002703 /*
2704 * start interpreting the command
2705 */
Owen Taylor3473f882001-02-23 17:55:21 +00002706 if (!strcmp(command, "exit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002707 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002708 if (!strcmp(command, "quit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002709 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002710 if (!strcmp(command, "bye"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002711 break;
Daniel Veillard5004f422001-11-08 13:53:05 +00002712 if (!strcmp(command, "help")) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002713 fprintf(ctxt->output, "\tbase display XML base of the node\n");
2714 fprintf(ctxt->output, "\tsetbase URI change the XML base of the node\n");
2715 fprintf(ctxt->output, "\tbye leave shell\n");
2716 fprintf(ctxt->output, "\tcat [node] display node or current node\n");
2717 fprintf(ctxt->output, "\tcd [path] change directory to path or to root\n");
2718 fprintf(ctxt->output, "\tdir [path] dumps informations about the node (namespace, attributes, content)\n");
2719 fprintf(ctxt->output, "\tdu [path] show the structure of the subtree under path or the current node\n");
2720 fprintf(ctxt->output, "\texit leave shell\n");
2721 fprintf(ctxt->output, "\thelp display this help\n");
2722 fprintf(ctxt->output, "\tfree display memory usage\n");
2723 fprintf(ctxt->output, "\tload [name] load a new document with name\n");
2724 fprintf(ctxt->output, "\tls [path] list contents of path or the current directory\n");
Daniel Veillardc14c3892004-08-16 12:34:50 +00002725 fprintf(ctxt->output, "\tset xml_fragment replace the current node content with the fragment parsed in context\n");
Daniel Veillard2070c482002-01-22 22:12:19 +00002726#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard321be0c2002-10-08 21:26:42 +00002727 fprintf(ctxt->output, "\txpath expr evaluate the XPath expression in that context and print the result\n");
Daniel Veillardbbaa9972004-06-16 14:08:33 +00002728 fprintf(ctxt->output, "\tsetns nsreg register a namespace to a prefix in the XPath evaluation context\n");
2729 fprintf(ctxt->output, "\t format for nsreg is: prefix=[nsuri] (i.e. prefix= unsets a prefix)\n");
Daniel Veillard2070c482002-01-22 22:12:19 +00002730#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard321be0c2002-10-08 21:26:42 +00002731 fprintf(ctxt->output, "\tpwd display current working directory\n");
2732 fprintf(ctxt->output, "\tquit leave shell\n");
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002733#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard321be0c2002-10-08 21:26:42 +00002734 fprintf(ctxt->output, "\tsave [name] save this document to name or the original name\n");
Daniel Veillard321be0c2002-10-08 21:26:42 +00002735 fprintf(ctxt->output, "\twrite [name] write the current node to the filename\n");
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002736#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillardf54cd532004-02-25 11:52:31 +00002737#ifdef LIBXML_VALID_ENABLED
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002738 fprintf(ctxt->output, "\tvalidate check the document for errors\n");
Daniel Veillardf54cd532004-02-25 11:52:31 +00002739#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard522bc602004-02-21 11:53:09 +00002740#ifdef LIBXML_SCHEMAS_ENABLED
2741 fprintf(ctxt->output, "\trelaxng rng validate the document agaisnt the Relax-NG schemas\n");
2742#endif
Daniel Veillard1e208222002-10-22 14:25:25 +00002743 fprintf(ctxt->output, "\tgrep string search for a string in the subtree\n");
Daniel Veillardf54cd532004-02-25 11:52:31 +00002744#ifdef LIBXML_VALID_ENABLED
Daniel Veillard5004f422001-11-08 13:53:05 +00002745 } else if (!strcmp(command, "validate")) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002746 xmlShellValidate(ctxt, arg, NULL, NULL);
Daniel Veillardf54cd532004-02-25 11:52:31 +00002747#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00002748 } else if (!strcmp(command, "load")) {
2749 xmlShellLoad(ctxt, arg, NULL, NULL);
Daniel Veillard522bc602004-02-21 11:53:09 +00002750#ifdef LIBXML_SCHEMAS_ENABLED
2751 } else if (!strcmp(command, "relaxng")) {
2752 xmlShellRNGValidate(ctxt, arg, NULL, NULL);
2753#endif
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002754#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002755 } else if (!strcmp(command, "save")) {
2756 xmlShellSave(ctxt, arg, NULL, NULL);
2757 } else if (!strcmp(command, "write")) {
2758 xmlShellWrite(ctxt, arg, NULL, NULL);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002759#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard1e208222002-10-22 14:25:25 +00002760 } else if (!strcmp(command, "grep")) {
2761 xmlShellGrep(ctxt, arg, ctxt->node, NULL);
Daniel Veillard78d12092001-10-11 09:12:24 +00002762 } else if (!strcmp(command, "free")) {
2763 if (arg[0] == 0) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002764 xmlMemShow(ctxt->output, 0);
Daniel Veillard78d12092001-10-11 09:12:24 +00002765 } else {
2766 int len = 0;
Owen Taylor3473f882001-02-23 17:55:21 +00002767
Daniel Veillard78d12092001-10-11 09:12:24 +00002768 sscanf(arg, "%d", &len);
Daniel Veillard321be0c2002-10-08 21:26:42 +00002769 xmlMemShow(ctxt->output, len);
Daniel Veillard78d12092001-10-11 09:12:24 +00002770 }
2771 } else if (!strcmp(command, "pwd")) {
2772 char dir[500];
Owen Taylor3473f882001-02-23 17:55:21 +00002773
Daniel Veillard78d12092001-10-11 09:12:24 +00002774 if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
Daniel Veillard321be0c2002-10-08 21:26:42 +00002775 fprintf(ctxt->output, "%s\n", dir);
Daniel Veillard78d12092001-10-11 09:12:24 +00002776 } else if (!strcmp(command, "du")) {
2777 xmlShellDu(ctxt, NULL, ctxt->node, NULL);
2778 } else if (!strcmp(command, "base")) {
2779 xmlShellBase(ctxt, NULL, ctxt->node, NULL);
Daniel Veillard29b17482004-08-16 00:39:03 +00002780 } else if (!strcmp(command, "set")) {
2781 xmlShellSetContent(ctxt, arg, ctxt->node, NULL);
Daniel Veillard2070c482002-01-22 22:12:19 +00002782#ifdef LIBXML_XPATH_ENABLED
Daniel Veillardbbaa9972004-06-16 14:08:33 +00002783 } else if (!strcmp(command, "setns")) {
2784 if (arg[0] == 0) {
2785 xmlGenericError(xmlGenericErrorContext,
2786 "setns: prefix=[nsuri] required\n");
2787 } else {
2788 xmlShellRegisterNamespace(ctxt, arg, NULL, NULL);
2789 }
Daniel Veillard2070c482002-01-22 22:12:19 +00002790 } else if (!strcmp(command, "xpath")) {
2791 if (arg[0] == 0) {
2792 xmlGenericError(xmlGenericErrorContext,
2793 "xpath: expression required\n");
2794 } else {
2795 ctxt->pctxt->node = ctxt->node;
2796 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
Daniel Veillard321be0c2002-10-08 21:26:42 +00002797 xmlXPathDebugDumpObject(ctxt->output, list, 0);
Daniel Veillard2070c482002-01-22 22:12:19 +00002798 xmlXPathFreeObject(list);
2799 }
2800#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard2156d432004-03-04 15:59:36 +00002801#ifdef LIBXML_TREE_ENABLED
Daniel Veillardcfa0d812002-01-17 08:46:58 +00002802 } else if (!strcmp(command, "setbase")) {
2803 xmlShellSetBase(ctxt, arg, ctxt->node, NULL);
Daniel Veillard2156d432004-03-04 15:59:36 +00002804#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00002805 } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) {
2806 int dir = (!strcmp(command, "dir"));
2807
2808 if (arg[0] == 0) {
2809 if (dir)
2810 xmlShellDir(ctxt, NULL, ctxt->node, NULL);
2811 else
2812 xmlShellList(ctxt, NULL, ctxt->node, NULL);
2813 } else {
2814 ctxt->pctxt->node = ctxt->node;
Daniel Veillard61d80a22001-04-27 17:13:01 +00002815#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002816 ctxt->pctxt->node = ctxt->node;
2817 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2818#else
2819 list = NULL;
2820#endif /* LIBXML_XPATH_ENABLED */
2821 if (list != NULL) {
2822 switch (list->type) {
2823 case XPATH_UNDEFINED:
2824 xmlGenericError(xmlGenericErrorContext,
2825 "%s: no such node\n", arg);
2826 break;
2827 case XPATH_NODESET:{
2828 int indx;
2829
Daniel Veillarda6825e82001-11-07 13:33:59 +00002830 if (list->nodesetval == NULL)
2831 break;
2832
Daniel Veillard78d12092001-10-11 09:12:24 +00002833 for (indx = 0;
2834 indx < list->nodesetval->nodeNr;
2835 indx++) {
2836 if (dir)
2837 xmlShellDir(ctxt, NULL,
2838 list->nodesetval->
2839 nodeTab[indx], NULL);
2840 else
2841 xmlShellList(ctxt, NULL,
2842 list->nodesetval->
2843 nodeTab[indx], NULL);
2844 }
2845 break;
2846 }
2847 case XPATH_BOOLEAN:
2848 xmlGenericError(xmlGenericErrorContext,
2849 "%s is a Boolean\n", arg);
2850 break;
2851 case XPATH_NUMBER:
2852 xmlGenericError(xmlGenericErrorContext,
2853 "%s is a number\n", arg);
2854 break;
2855 case XPATH_STRING:
2856 xmlGenericError(xmlGenericErrorContext,
2857 "%s is a string\n", arg);
2858 break;
2859 case XPATH_POINT:
2860 xmlGenericError(xmlGenericErrorContext,
2861 "%s is a point\n", arg);
2862 break;
2863 case XPATH_RANGE:
2864 xmlGenericError(xmlGenericErrorContext,
2865 "%s is a range\n", arg);
2866 break;
2867 case XPATH_LOCATIONSET:
2868 xmlGenericError(xmlGenericErrorContext,
2869 "%s is a range\n", arg);
2870 break;
2871 case XPATH_USERS:
2872 xmlGenericError(xmlGenericErrorContext,
2873 "%s is user-defined\n", arg);
2874 break;
2875 case XPATH_XSLT_TREE:
2876 xmlGenericError(xmlGenericErrorContext,
2877 "%s is an XSLT value tree\n",
2878 arg);
2879 break;
2880 }
2881#ifdef LIBXML_XPATH_ENABLED
2882 xmlXPathFreeObject(list);
Daniel Veillard61d80a22001-04-27 17:13:01 +00002883#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00002884 } else {
2885 xmlGenericError(xmlGenericErrorContext,
2886 "%s: no such node\n", arg);
2887 }
2888 ctxt->pctxt->node = NULL;
2889 }
2890 } else if (!strcmp(command, "cd")) {
2891 if (arg[0] == 0) {
2892 ctxt->node = (xmlNodePtr) ctxt->doc;
2893 } else {
2894#ifdef LIBXML_XPATH_ENABLED
2895 ctxt->pctxt->node = ctxt->node;
2896 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2897#else
2898 list = NULL;
2899#endif /* LIBXML_XPATH_ENABLED */
2900 if (list != NULL) {
2901 switch (list->type) {
2902 case XPATH_UNDEFINED:
2903 xmlGenericError(xmlGenericErrorContext,
2904 "%s: no such node\n", arg);
2905 break;
2906 case XPATH_NODESET:
Daniel Veillarda6825e82001-11-07 13:33:59 +00002907 if (list->nodesetval != NULL) {
2908 if (list->nodesetval->nodeNr == 1) {
2909 ctxt->node = list->nodesetval->nodeTab[0];
Daniel Veillard7a985a12003-07-06 17:57:42 +00002910 if ((ctxt->node != NULL) &&
2911 (ctxt->node->type ==
2912 XML_NAMESPACE_DECL)) {
2913 xmlGenericError(xmlGenericErrorContext,
2914 "cannot cd to namespace\n");
2915 ctxt->node = NULL;
2916 }
Daniel Veillarda6825e82001-11-07 13:33:59 +00002917 } else
2918 xmlGenericError(xmlGenericErrorContext,
2919 "%s is a %d Node Set\n",
2920 arg,
2921 list->nodesetval->nodeNr);
Daniel Veillard78d12092001-10-11 09:12:24 +00002922 } else
2923 xmlGenericError(xmlGenericErrorContext,
Daniel Veillarda6825e82001-11-07 13:33:59 +00002924 "%s is an empty Node Set\n",
2925 arg);
Daniel Veillard78d12092001-10-11 09:12:24 +00002926 break;
2927 case XPATH_BOOLEAN:
2928 xmlGenericError(xmlGenericErrorContext,
2929 "%s is a Boolean\n", arg);
2930 break;
2931 case XPATH_NUMBER:
2932 xmlGenericError(xmlGenericErrorContext,
2933 "%s is a number\n", arg);
2934 break;
2935 case XPATH_STRING:
2936 xmlGenericError(xmlGenericErrorContext,
2937 "%s is a string\n", arg);
2938 break;
2939 case XPATH_POINT:
2940 xmlGenericError(xmlGenericErrorContext,
2941 "%s is a point\n", arg);
2942 break;
2943 case XPATH_RANGE:
2944 xmlGenericError(xmlGenericErrorContext,
2945 "%s is a range\n", arg);
2946 break;
2947 case XPATH_LOCATIONSET:
2948 xmlGenericError(xmlGenericErrorContext,
2949 "%s is a range\n", arg);
2950 break;
2951 case XPATH_USERS:
2952 xmlGenericError(xmlGenericErrorContext,
2953 "%s is user-defined\n", arg);
2954 break;
2955 case XPATH_XSLT_TREE:
2956 xmlGenericError(xmlGenericErrorContext,
2957 "%s is an XSLT value tree\n",
2958 arg);
2959 break;
2960 }
2961#ifdef LIBXML_XPATH_ENABLED
2962 xmlXPathFreeObject(list);
2963#endif
2964 } else {
2965 xmlGenericError(xmlGenericErrorContext,
2966 "%s: no such node\n", arg);
2967 }
2968 ctxt->pctxt->node = NULL;
2969 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002970#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002971 } else if (!strcmp(command, "cat")) {
2972 if (arg[0] == 0) {
2973 xmlShellCat(ctxt, NULL, ctxt->node, NULL);
2974 } else {
2975 ctxt->pctxt->node = ctxt->node;
2976#ifdef LIBXML_XPATH_ENABLED
2977 ctxt->pctxt->node = ctxt->node;
2978 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2979#else
2980 list = NULL;
2981#endif /* LIBXML_XPATH_ENABLED */
2982 if (list != NULL) {
2983 switch (list->type) {
2984 case XPATH_UNDEFINED:
2985 xmlGenericError(xmlGenericErrorContext,
2986 "%s: no such node\n", arg);
2987 break;
2988 case XPATH_NODESET:{
2989 int indx;
2990
Daniel Veillarda6825e82001-11-07 13:33:59 +00002991 if (list->nodesetval == NULL)
2992 break;
2993
Daniel Veillard78d12092001-10-11 09:12:24 +00002994 for (indx = 0;
2995 indx < list->nodesetval->nodeNr;
2996 indx++) {
2997 if (i > 0)
Daniel Veillard321be0c2002-10-08 21:26:42 +00002998 fprintf(ctxt->output, " -------\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00002999 xmlShellCat(ctxt, NULL,
3000 list->nodesetval->
3001 nodeTab[indx], NULL);
3002 }
3003 break;
3004 }
3005 case XPATH_BOOLEAN:
3006 xmlGenericError(xmlGenericErrorContext,
3007 "%s is a Boolean\n", arg);
3008 break;
3009 case XPATH_NUMBER:
3010 xmlGenericError(xmlGenericErrorContext,
3011 "%s is a number\n", arg);
3012 break;
3013 case XPATH_STRING:
3014 xmlGenericError(xmlGenericErrorContext,
3015 "%s is a string\n", arg);
3016 break;
3017 case XPATH_POINT:
3018 xmlGenericError(xmlGenericErrorContext,
3019 "%s is a point\n", arg);
3020 break;
3021 case XPATH_RANGE:
3022 xmlGenericError(xmlGenericErrorContext,
3023 "%s is a range\n", arg);
3024 break;
3025 case XPATH_LOCATIONSET:
3026 xmlGenericError(xmlGenericErrorContext,
3027 "%s is a range\n", arg);
3028 break;
3029 case XPATH_USERS:
3030 xmlGenericError(xmlGenericErrorContext,
3031 "%s is user-defined\n", arg);
3032 break;
3033 case XPATH_XSLT_TREE:
3034 xmlGenericError(xmlGenericErrorContext,
3035 "%s is an XSLT value tree\n",
3036 arg);
3037 break;
3038 }
3039#ifdef LIBXML_XPATH_ENABLED
3040 xmlXPathFreeObject(list);
3041#endif
3042 } else {
3043 xmlGenericError(xmlGenericErrorContext,
3044 "%s: no such node\n", arg);
3045 }
3046 ctxt->pctxt->node = NULL;
3047 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003048#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00003049 } else {
3050 xmlGenericError(xmlGenericErrorContext,
3051 "Unknown command %s\n", command);
3052 }
3053 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00003054 }
3055#ifdef LIBXML_XPATH_ENABLED
3056 xmlXPathFreeContext(ctxt->pctxt);
3057#endif /* LIBXML_XPATH_ENABLED */
3058 if (ctxt->loaded) {
3059 xmlFreeDoc(ctxt->doc);
3060 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00003061 if (ctxt->filename != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00003062 xmlFree(ctxt->filename);
Owen Taylor3473f882001-02-23 17:55:21 +00003063 xmlFree(ctxt);
3064 if (cmdline != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00003065 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00003066}
3067
3068#endif /* LIBXML_DEBUG_ENABLED */