blob: afc0114ba2d600078b93824c08818aaab4b9104a [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
William M. Brack9638d4c2004-10-15 18:25:33 +000066xmlCtxtDumpCleanCtxt(xmlDebugCtxtPtr ctxt ATTRIBUTE_UNUSED)
Daniel Veillard76821142004-10-09 20:39:04 +000067{
William M. Brack9638d4c2004-10-15 18:25:33 +000068 /* remove the ATTRIBUTE_UNUSED when this is added */
Daniel Veillard76821142004-10-09 20:39:04 +000069}
70
71/**
Daniel Veillard0d24b112004-10-11 12:28:34 +000072 * xmlNsCheckScope:
73 * @node: the node
74 * @ns: the namespace node
Daniel Veillard76821142004-10-09 20:39:04 +000075 *
Daniel Veillard0d24b112004-10-11 12:28:34 +000076 * Check that a given namespace is in scope on a node.
Daniel Veillard76821142004-10-09 20:39:04 +000077 *
Daniel Veillard0d24b112004-10-11 12:28:34 +000078 * Returns 1 if in scope, -1 in case of argument error,
79 * -2 if the namespace is not in scope, and -3 if not on
80 * an ancestor node.
Daniel Veillard76821142004-10-09 20:39:04 +000081 */
82static int
Daniel Veillard0d24b112004-10-11 12:28:34 +000083xmlNsCheckScope(xmlNodePtr node, xmlNsPtr ns)
Daniel Veillard76821142004-10-09 20:39:04 +000084{
Daniel Veillard0d24b112004-10-11 12:28:34 +000085 xmlNsPtr cur;
Daniel Veillard76821142004-10-09 20:39:04 +000086
Daniel Veillard0d24b112004-10-11 12:28:34 +000087 if ((node == NULL) || (ns == NULL))
88 return(-1);
89
90 if ((node->type != XML_ELEMENT_NODE) &&
91 (node->type != XML_ATTRIBUTE_NODE) &&
92 (node->type != XML_DOCUMENT_NODE) &&
93 (node->type != XML_TEXT_NODE) &&
94 (node->type != XML_HTML_DOCUMENT_NODE) &&
95 (node->type != XML_XINCLUDE_START))
96 return(-2);
97
98 while ((node != NULL) &&
99 ((node->type == XML_ELEMENT_NODE) ||
100 (node->type == XML_ATTRIBUTE_NODE) ||
101 (node->type == XML_TEXT_NODE) ||
102 (node->type == XML_XINCLUDE_START))) {
103 if ((node->type == XML_ELEMENT_NODE) ||
104 (node->type == XML_XINCLUDE_START)) {
105 cur = node->nsDef;
106 while (cur != NULL) {
107 if (cur == ns)
108 return(1);
109 if (xmlStrEqual(cur->prefix, ns->prefix))
110 return(-2);
111 cur = cur->next;
112 }
Daniel Veillard76821142004-10-09 20:39:04 +0000113 }
Daniel Veillard0d24b112004-10-11 12:28:34 +0000114 node = node->parent;
Daniel Veillard76821142004-10-09 20:39:04 +0000115 }
Daniel Veillard0d24b112004-10-11 12:28:34 +0000116 /* the xml namespace may be declared on the document node */
117 if ((node != NULL) &&
118 ((node->type == XML_DOCUMENT_NODE) ||
119 (node->type == XML_HTML_DOCUMENT_NODE))) {
120 xmlNsPtr oldNs = ((xmlDocPtr) node)->oldNs;
121 if (oldNs == ns)
122 return(1);
123 }
124 return(-3);
Daniel Veillard76821142004-10-09 20:39:04 +0000125}
Daniel Veillard76821142004-10-09 20:39:04 +0000126
Daniel Veillard76821142004-10-09 20:39:04 +0000127static void
Daniel Veillard22cdb842004-10-04 14:09:17 +0000128xmlCtxtDumpSpaces(xmlDebugCtxtPtr ctxt)
129{
130 if (ctxt->check)
131 return;
132 if ((ctxt->output != NULL) && (ctxt->depth > 0)) {
133 if (ctxt->depth < 50)
134 fprintf(ctxt->output, &ctxt->shift[100 - 2 * ctxt->depth]);
135 else
136 fprintf(ctxt->output, ctxt->shift);
137 }
138}
139
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000140/**
141 * xmlDebugErr:
142 * @ctxt: a debug context
143 * @error: the error code
144 *
145 * Handle a debug error.
146 */
147static void
148xmlDebugErr(xmlDebugCtxtPtr ctxt, int error, const char *msg)
149{
150 ctxt->errors++;
151 __xmlRaiseError(NULL, NULL, NULL,
152 NULL, ctxt->node, XML_FROM_CHECK,
153 error, XML_ERR_ERROR, NULL, 0,
154 NULL, NULL, NULL, 0, 0,
155 msg);
156}
157static void
158xmlDebugErr2(xmlDebugCtxtPtr ctxt, int error, const char *msg, int extra)
159{
160 ctxt->errors++;
161 __xmlRaiseError(NULL, NULL, NULL,
162 NULL, ctxt->node, XML_FROM_CHECK,
163 error, XML_ERR_ERROR, NULL, 0,
164 NULL, NULL, NULL, 0, 0,
165 msg, extra);
166}
167static void
Daniel Veillardc6095782004-10-15 14:50:10 +0000168xmlDebugErr3(xmlDebugCtxtPtr ctxt, int error, const char *msg, const char *extra)
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000169{
170 ctxt->errors++;
171 __xmlRaiseError(NULL, NULL, NULL,
172 NULL, ctxt->node, XML_FROM_CHECK,
173 error, XML_ERR_ERROR, NULL, 0,
174 NULL, NULL, NULL, 0, 0,
175 msg, extra);
176}
177
Daniel Veillard0d24b112004-10-11 12:28:34 +0000178/**
179 * xmlCtxtNsCheckScope:
180 * @ctxt: the debugging context
181 * @node: the node
182 * @ns: the namespace node
183 *
184 * Report if a given namespace is is not in scope.
185 */
186static void
187xmlCtxtNsCheckScope(xmlDebugCtxtPtr ctxt, xmlNodePtr node, xmlNsPtr ns)
188{
189 int ret;
190
191 ret = xmlNsCheckScope(node, ns);
192 if (ret == -2) {
193 if (ns->prefix == NULL)
194 xmlDebugErr(ctxt, XML_CHECK_NS_SCOPE,
195 "Reference to default namespace not in scope\n");
196 else
197 xmlDebugErr3(ctxt, XML_CHECK_NS_SCOPE,
198 "Reference to namespace '%s' not in scope\n",
199 (char *) ns->prefix);
200 }
201 if (ret == -3) {
202 if (ns->prefix == NULL)
203 xmlDebugErr(ctxt, XML_CHECK_NS_ANCESTOR,
204 "Reference to default namespace not on ancestor\n");
205 else
206 xmlDebugErr3(ctxt, XML_CHECK_NS_ANCESTOR,
207 "Reference to namespace '%s' not on ancestor\n",
208 (char *) ns->prefix);
209 }
210}
211
Daniel Veillardc6095782004-10-15 14:50:10 +0000212/**
213 * xmlCtxtCheckString:
214 * @ctxt: the debug context
215 * @str: the string
216 *
217 * Do debugging on the string, currently it just checks the UTF-8 content
218 */
219static void
220xmlCtxtCheckString(xmlDebugCtxtPtr ctxt, const xmlChar * str)
221{
222 if (str == NULL) return;
223 if (ctxt->check) {
224 if (!xmlCheckUTF8(str)) {
225 xmlDebugErr3(ctxt, XML_CHECK_NOT_DTD,
226 "String is not UTF-8 %s", (const char *) str);
227 }
228 }
229}
230
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000231static void
232xmlCtxtGenericNodeCheck(xmlDebugCtxtPtr ctxt, xmlNodePtr node) {
233 if (node->parent == NULL)
234 xmlDebugErr(ctxt, XML_CHECK_NO_PARENT,
235 "Node has no parent\n");
236 if (node->doc == NULL)
237 xmlDebugErr(ctxt, XML_CHECK_NO_DOC,
238 "Node has no doc\n");
239 if ((node->parent != NULL) && (node->doc != node->parent->doc) &&
240 (!xmlStrEqual(node->name, BAD_CAST "pseudoroot")))
241 xmlDebugErr(ctxt, XML_CHECK_WRONG_DOC,
242 "Node doc differs from parent's one\n");
243 if (node->prev == NULL) {
244 if (node->type == XML_ATTRIBUTE_NODE) {
245 if ((node->parent != NULL) &&
246 (node != (xmlNodePtr) node->parent->properties))
247 xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
248 "Attr has no prev and not first of attr list\n");
249
250 } else if ((node->parent != NULL) && (node->parent->children != node))
251 xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
252 "Node has no prev and not first of parent list\n");
253 } else {
254 if (node->prev->next != node)
255 xmlDebugErr(ctxt, XML_CHECK_WRONG_PREV,
256 "Node prev->next : back link wrong\n");
257 }
258 if (node->next == NULL) {
259 if ((node->parent != NULL) && (node->type != XML_ATTRIBUTE_NODE) &&
260 (node->parent->last != node))
261 xmlDebugErr(ctxt, XML_CHECK_NO_NEXT,
262 "Node has no next and not last of parent list\n");
263 } else {
264 if (node->next->prev != node)
265 xmlDebugErr(ctxt, XML_CHECK_WRONG_NEXT,
266 "Node next->prev : forward link wrong\n");
Daniel Veillard0d24b112004-10-11 12:28:34 +0000267 if (node->next->parent != node->parent)
268 xmlDebugErr(ctxt, XML_CHECK_WRONG_PARENT,
269 "Node next->prev : forward link wrong\n");
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000270 }
Daniel Veillard0d24b112004-10-11 12:28:34 +0000271 if (node->type == XML_ELEMENT_NODE) {
272 xmlNsPtr ns;
273
274 ns = node->nsDef;
275 while (ns != NULL) {
276 xmlCtxtNsCheckScope(ctxt, node, ns);
277 ns = ns->next;
278 }
279 if (node->ns != NULL)
280 xmlCtxtNsCheckScope(ctxt, node, node->ns);
281 } else if (node->type == XML_ATTRIBUTE_NODE) {
282 if (node->ns != NULL)
283 xmlCtxtNsCheckScope(ctxt, node, node->ns);
284 }
285
Daniel Veillardc6095782004-10-15 14:50:10 +0000286 if ((node->type != XML_ELEMENT_NODE) &&
William M. Brack9638d4c2004-10-15 18:25:33 +0000287 (node->type != XML_ATTRIBUTE_NODE) &&
288 (node->type != XML_ATTRIBUTE_DECL) &&
289 (node->type != XML_DTD_NODE) &&
290 (node->type != XML_HTML_DOCUMENT_NODE) &&
291 (node->type != XML_DOCUMENT_NODE)) {
Daniel Veillardc6095782004-10-15 14:50:10 +0000292 if (node->content != NULL)
William M. Brack9638d4c2004-10-15 18:25:33 +0000293 xmlCtxtCheckString(ctxt, (const xmlChar *) node->content);
Daniel Veillardc6095782004-10-15 14:50:10 +0000294 }
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000295}
296
Daniel Veillard22cdb842004-10-04 14:09:17 +0000297static void
298xmlCtxtDumpString(xmlDebugCtxtPtr ctxt, const xmlChar * str)
299{
300 int i;
301
Daniel Veillardc6095782004-10-15 14:50:10 +0000302 if (ctxt->check) {
Daniel Veillard22cdb842004-10-04 14:09:17 +0000303 return;
Daniel Veillardc6095782004-10-15 14:50:10 +0000304 }
Daniel Veillard22cdb842004-10-04 14:09:17 +0000305 /* TODO: check UTF8 content of the string */
306 if (str == NULL) {
307 fprintf(ctxt->output, "(NULL)");
308 return;
309 }
310 for (i = 0; i < 40; i++)
311 if (str[i] == 0)
312 return;
313 else if (IS_BLANK_CH(str[i]))
314 fputc(' ', ctxt->output);
315 else if (str[i] >= 0x80)
316 fprintf(ctxt->output, "#%X", str[i]);
317 else
318 fputc(str[i], ctxt->output);
319 fprintf(ctxt->output, "...");
320}
321
322static void
323xmlCtxtDumpDtdNode(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd)
324{
325 xmlCtxtDumpSpaces(ctxt);
326
327 if (dtd == NULL) {
328 if (!ctxt->check)
329 fprintf(ctxt->output, "DTD node is NULL\n");
330 return;
331 }
332
333 if (dtd->type != XML_DTD_NODE) {
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000334 xmlDebugErr(ctxt, XML_CHECK_NOT_DTD,
335 "Node is not a DTD");
Daniel Veillard22cdb842004-10-04 14:09:17 +0000336 return;
337 }
338 if (!ctxt->check) {
339 if (dtd->name != NULL)
340 fprintf(ctxt->output, "DTD(%s)", (char *) dtd->name);
341 else
342 fprintf(ctxt->output, "DTD");
343 if (dtd->ExternalID != NULL)
344 fprintf(ctxt->output, ", PUBLIC %s", (char *) dtd->ExternalID);
345 if (dtd->SystemID != NULL)
346 fprintf(ctxt->output, ", SYSTEM %s", (char *) dtd->SystemID);
347 fprintf(ctxt->output, "\n");
348 }
349 /*
350 * Do a bit of checking
351 */
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000352 xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) dtd);
Daniel Veillard22cdb842004-10-04 14:09:17 +0000353}
354
355static void
356xmlCtxtDumpAttrDecl(xmlDebugCtxtPtr ctxt, xmlAttributePtr attr)
357{
358 xmlCtxtDumpSpaces(ctxt);
359
360 if (attr == NULL) {
361 if (!ctxt->check)
362 fprintf(ctxt->output, "Attribute declaration is NULL\n");
363 return;
364 }
365 if (attr->type != XML_ATTRIBUTE_DECL) {
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000366 xmlDebugErr(ctxt, XML_CHECK_NOT_ATTR_DECL,
367 "Node is not an attribute declaration");
Daniel Veillard22cdb842004-10-04 14:09:17 +0000368 return;
369 }
370 if (attr->name != NULL) {
371 if (!ctxt->check)
372 fprintf(ctxt->output, "ATTRDECL(%s)", (char *) attr->name);
373 } else
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000374 xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
375 "Node attribute declaration has no name");
Daniel Veillard22cdb842004-10-04 14:09:17 +0000376 if (attr->elem != NULL) {
377 if (!ctxt->check)
378 fprintf(ctxt->output, " for %s", (char *) attr->elem);
379 } else
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000380 xmlDebugErr(ctxt, XML_CHECK_NO_ELEM,
381 "Node attribute declaration has no element name");
Daniel Veillard22cdb842004-10-04 14:09:17 +0000382 if (!ctxt->check) {
383 switch (attr->atype) {
384 case XML_ATTRIBUTE_CDATA:
385 fprintf(ctxt->output, " CDATA");
386 break;
387 case XML_ATTRIBUTE_ID:
388 fprintf(ctxt->output, " ID");
389 break;
390 case XML_ATTRIBUTE_IDREF:
391 fprintf(ctxt->output, " IDREF");
392 break;
393 case XML_ATTRIBUTE_IDREFS:
394 fprintf(ctxt->output, " IDREFS");
395 break;
396 case XML_ATTRIBUTE_ENTITY:
397 fprintf(ctxt->output, " ENTITY");
398 break;
399 case XML_ATTRIBUTE_ENTITIES:
400 fprintf(ctxt->output, " ENTITIES");
401 break;
402 case XML_ATTRIBUTE_NMTOKEN:
403 fprintf(ctxt->output, " NMTOKEN");
404 break;
405 case XML_ATTRIBUTE_NMTOKENS:
406 fprintf(ctxt->output, " NMTOKENS");
407 break;
408 case XML_ATTRIBUTE_ENUMERATION:
409 fprintf(ctxt->output, " ENUMERATION");
410 break;
411 case XML_ATTRIBUTE_NOTATION:
412 fprintf(ctxt->output, " NOTATION ");
413 break;
414 }
415 if (attr->tree != NULL) {
416 int indx;
417 xmlEnumerationPtr cur = attr->tree;
418
419 for (indx = 0; indx < 5; indx++) {
420 if (indx != 0)
421 fprintf(ctxt->output, "|%s", (char *) cur->name);
422 else
423 fprintf(ctxt->output, " (%s", (char *) cur->name);
424 cur = cur->next;
425 if (cur == NULL)
426 break;
427 }
428 if (cur == NULL)
429 fprintf(ctxt->output, ")");
430 else
431 fprintf(ctxt->output, "...)");
432 }
433 switch (attr->def) {
434 case XML_ATTRIBUTE_NONE:
435 break;
436 case XML_ATTRIBUTE_REQUIRED:
437 fprintf(ctxt->output, " REQUIRED");
438 break;
439 case XML_ATTRIBUTE_IMPLIED:
440 fprintf(ctxt->output, " IMPLIED");
441 break;
442 case XML_ATTRIBUTE_FIXED:
443 fprintf(ctxt->output, " FIXED");
444 break;
445 }
446 if (attr->defaultValue != NULL) {
447 fprintf(ctxt->output, "\"");
448 xmlCtxtDumpString(ctxt, attr->defaultValue);
449 fprintf(ctxt->output, "\"");
450 }
451 fprintf(ctxt->output, "\n");
452 }
453
454 /*
455 * Do a bit of checking
456 */
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000457 xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr);
Daniel Veillard22cdb842004-10-04 14:09:17 +0000458}
459
460static void
461xmlCtxtDumpElemDecl(xmlDebugCtxtPtr ctxt, xmlElementPtr elem)
462{
463 xmlCtxtDumpSpaces(ctxt);
464
465 if (elem == NULL) {
466 if (!ctxt->check)
467 fprintf(ctxt->output, "Element declaration is NULL\n");
468 return;
469 }
470 if (elem->type != XML_ELEMENT_DECL) {
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000471 xmlDebugErr(ctxt, XML_CHECK_NOT_ELEM_DECL,
472 "Node is not an element declaration");
Daniel Veillard22cdb842004-10-04 14:09:17 +0000473 return;
474 }
475 if (elem->name != NULL) {
476 if (!ctxt->check) {
477 fprintf(ctxt->output, "ELEMDECL(");
478 xmlCtxtDumpString(ctxt, elem->name);
479 fprintf(ctxt->output, ")");
480 }
481 } else
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000482 xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
483 "Element declaration has no name");
Daniel Veillard22cdb842004-10-04 14:09:17 +0000484 if (!ctxt->check) {
485 switch (elem->etype) {
486 case XML_ELEMENT_TYPE_UNDEFINED:
487 fprintf(ctxt->output, ", UNDEFINED");
488 break;
489 case XML_ELEMENT_TYPE_EMPTY:
490 fprintf(ctxt->output, ", EMPTY");
491 break;
492 case XML_ELEMENT_TYPE_ANY:
493 fprintf(ctxt->output, ", ANY");
494 break;
495 case XML_ELEMENT_TYPE_MIXED:
496 fprintf(ctxt->output, ", MIXED ");
497 break;
498 case XML_ELEMENT_TYPE_ELEMENT:
499 fprintf(ctxt->output, ", MIXED ");
500 break;
501 }
502 if ((elem->type != XML_ELEMENT_NODE) && (elem->content != NULL)) {
503 char buf[5001];
504
505 buf[0] = 0;
506 xmlSnprintfElementContent(buf, 5000, elem->content, 1);
507 buf[5000] = 0;
508 fprintf(ctxt->output, "%s", buf);
509 }
510 fprintf(ctxt->output, "\n");
511 }
512
513 /*
514 * Do a bit of checking
515 */
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000516 xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) elem);
Daniel Veillard22cdb842004-10-04 14:09:17 +0000517}
518
519static void
520xmlCtxtDumpEntityDecl(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent)
521{
522 xmlCtxtDumpSpaces(ctxt);
523
524 if (ent == NULL) {
525 if (!ctxt->check)
526 fprintf(ctxt->output, "Entity declaration is NULL\n");
527 return;
528 }
529 if (ent->type != XML_ENTITY_DECL) {
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000530 xmlDebugErr(ctxt, XML_CHECK_NOT_ENTITY_DECL,
531 "Node is not an entity declaration");
Daniel Veillard22cdb842004-10-04 14:09:17 +0000532 return;
533 }
534 if (ent->name != NULL) {
535 if (!ctxt->check) {
536 fprintf(ctxt->output, "ENTITYDECL(");
537 xmlCtxtDumpString(ctxt, ent->name);
538 fprintf(ctxt->output, ")");
539 }
540 } else
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000541 xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
542 "Entity declaration has no name");
Daniel Veillard22cdb842004-10-04 14:09:17 +0000543 if (!ctxt->check) {
544 switch (ent->etype) {
545 case XML_INTERNAL_GENERAL_ENTITY:
546 fprintf(ctxt->output, ", internal\n");
547 break;
548 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
549 fprintf(ctxt->output, ", external parsed\n");
550 break;
551 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
552 fprintf(ctxt->output, ", unparsed\n");
553 break;
554 case XML_INTERNAL_PARAMETER_ENTITY:
555 fprintf(ctxt->output, ", parameter\n");
556 break;
557 case XML_EXTERNAL_PARAMETER_ENTITY:
558 fprintf(ctxt->output, ", external parameter\n");
559 break;
560 case XML_INTERNAL_PREDEFINED_ENTITY:
561 fprintf(ctxt->output, ", predefined\n");
562 break;
563 }
564 if (ent->ExternalID) {
565 xmlCtxtDumpSpaces(ctxt);
566 fprintf(ctxt->output, " ExternalID=%s\n",
567 (char *) ent->ExternalID);
568 }
569 if (ent->SystemID) {
570 xmlCtxtDumpSpaces(ctxt);
571 fprintf(ctxt->output, " SystemID=%s\n",
572 (char *) ent->SystemID);
573 }
574 if (ent->URI != NULL) {
575 xmlCtxtDumpSpaces(ctxt);
576 fprintf(ctxt->output, " URI=%s\n", (char *) ent->URI);
577 }
578 if (ent->content) {
579 xmlCtxtDumpSpaces(ctxt);
580 fprintf(ctxt->output, " content=");
581 xmlCtxtDumpString(ctxt, ent->content);
582 fprintf(ctxt->output, "\n");
583 }
584 }
585
586 /*
587 * Do a bit of checking
588 */
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000589 xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) ent);
Daniel Veillard22cdb842004-10-04 14:09:17 +0000590}
591
592static void
593xmlCtxtDumpNamespace(xmlDebugCtxtPtr ctxt, xmlNsPtr ns)
594{
595 xmlCtxtDumpSpaces(ctxt);
596
597 if (ns == NULL) {
598 if (!ctxt->check)
599 fprintf(ctxt->output, "namespace node is NULL\n");
600 return;
601 }
602 if (ns->type != XML_NAMESPACE_DECL) {
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000603 xmlDebugErr(ctxt, XML_CHECK_NOT_NS_DECL,
604 "Node is not a namespace declaration");
Daniel Veillard22cdb842004-10-04 14:09:17 +0000605 return;
606 }
607 if (ns->href == NULL) {
608 if (ns->prefix != NULL)
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000609 xmlDebugErr3(ctxt, XML_CHECK_NO_HREF,
610 "Incomplete namespace %s href=NULL\n",
Daniel Veillard22cdb842004-10-04 14:09:17 +0000611 (char *) ns->prefix);
612 else
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000613 xmlDebugErr(ctxt, XML_CHECK_NO_HREF,
614 "Incomplete default namespace href=NULL\n");
Daniel Veillard22cdb842004-10-04 14:09:17 +0000615 } else {
616 if (!ctxt->check) {
617 if (ns->prefix != NULL)
618 fprintf(ctxt->output, "namespace %s href=",
619 (char *) ns->prefix);
620 else
621 fprintf(ctxt->output, "default namespace href=");
622
623 xmlCtxtDumpString(ctxt, ns->href);
624 fprintf(ctxt->output, "\n");
625 }
626 }
627}
628
629static void
630xmlCtxtDumpNamespaceList(xmlDebugCtxtPtr ctxt, xmlNsPtr ns)
631{
632 while (ns != NULL) {
633 xmlCtxtDumpNamespace(ctxt, ns);
634 ns = ns->next;
635 }
636}
637
638static void
639xmlCtxtDumpEntity(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent)
640{
641 xmlCtxtDumpSpaces(ctxt);
642
643 if (ent == NULL) {
644 if (!ctxt->check)
645 fprintf(ctxt->output, "Entity is NULL\n");
646 return;
647 }
648 if (!ctxt->check) {
649 switch (ent->etype) {
650 case XML_INTERNAL_GENERAL_ENTITY:
651 fprintf(ctxt->output, "INTERNAL_GENERAL_ENTITY ");
652 break;
653 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
654 fprintf(ctxt->output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
655 break;
656 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
657 fprintf(ctxt->output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
658 break;
659 case XML_INTERNAL_PARAMETER_ENTITY:
660 fprintf(ctxt->output, "INTERNAL_PARAMETER_ENTITY ");
661 break;
662 case XML_EXTERNAL_PARAMETER_ENTITY:
663 fprintf(ctxt->output, "EXTERNAL_PARAMETER_ENTITY ");
664 break;
665 default:
666 fprintf(ctxt->output, "ENTITY_%d ! ", (int) ent->etype);
667 }
668 fprintf(ctxt->output, "%s\n", ent->name);
669 if (ent->ExternalID) {
670 xmlCtxtDumpSpaces(ctxt);
671 fprintf(ctxt->output, "ExternalID=%s\n",
672 (char *) ent->ExternalID);
673 }
674 if (ent->SystemID) {
675 xmlCtxtDumpSpaces(ctxt);
676 fprintf(ctxt->output, "SystemID=%s\n", (char *) ent->SystemID);
677 }
678 if (ent->URI) {
679 xmlCtxtDumpSpaces(ctxt);
680 fprintf(ctxt->output, "URI=%s\n", (char *) ent->URI);
681 }
682 if (ent->content) {
683 xmlCtxtDumpSpaces(ctxt);
684 fprintf(ctxt->output, "content=");
685 xmlCtxtDumpString(ctxt, ent->content);
686 fprintf(ctxt->output, "\n");
687 }
688 }
689}
690
691/**
692 * xmlCtxtDumpAttr:
693 * @output: the FILE * for the output
694 * @attr: the attribute
695 * @depth: the indentation level.
696 *
697 * Dumps debug information for the attribute
698 */
699static void
700xmlCtxtDumpAttr(xmlDebugCtxtPtr ctxt, xmlAttrPtr attr)
701{
702 xmlCtxtDumpSpaces(ctxt);
703
704 if (attr == NULL) {
705 if (!ctxt->check)
706 fprintf(ctxt->output, "Attr is NULL");
707 return;
708 }
709 if (!ctxt->check) {
710 fprintf(ctxt->output, "ATTRIBUTE ");
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000711 xmlCtxtDumpString(ctxt, attr->name);
Daniel Veillard22cdb842004-10-04 14:09:17 +0000712 fprintf(ctxt->output, "\n");
713 if (attr->children != NULL) {
714 ctxt->depth++;
715 xmlCtxtDumpNodeList(ctxt, attr->children);
716 ctxt->depth--;
717 }
718 }
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000719 if (attr->name == NULL)
720 xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
721 "Attribute has no name");
Daniel Veillard22cdb842004-10-04 14:09:17 +0000722
723 /*
724 * Do a bit of checking
725 */
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000726 xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr);
Daniel Veillard22cdb842004-10-04 14:09:17 +0000727}
728
729/**
730 * xmlCtxtDumpAttrList:
731 * @output: the FILE * for the output
732 * @attr: the attribute list
733 * @depth: the indentation level.
734 *
735 * Dumps debug information for the attribute list
736 */
737static void
738xmlCtxtDumpAttrList(xmlDebugCtxtPtr ctxt, xmlAttrPtr attr)
739{
740 while (attr != NULL) {
741 xmlCtxtDumpAttr(ctxt, attr);
742 attr = attr->next;
743 }
744}
745
746/**
747 * xmlCtxtDumpOneNode:
748 * @output: the FILE * for the output
749 * @node: the node
750 * @depth: the indentation level.
751 *
752 * Dumps debug information for the element node, it is not recursive
753 */
754static void
755xmlCtxtDumpOneNode(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
756{
757 if (node == NULL) {
758 if (!ctxt->check) {
759 xmlCtxtDumpSpaces(ctxt);
760 fprintf(ctxt->output, "node is NULL\n");
761 }
762 return;
763 }
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000764 ctxt->node = node;
765
Daniel Veillard22cdb842004-10-04 14:09:17 +0000766 switch (node->type) {
767 case XML_ELEMENT_NODE:
768 if (!ctxt->check) {
769 xmlCtxtDumpSpaces(ctxt);
770 fprintf(ctxt->output, "ELEMENT ");
771 if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
772 xmlCtxtDumpString(ctxt, node->ns->prefix);
773 fprintf(ctxt->output, ":");
774 }
775 xmlCtxtDumpString(ctxt, node->name);
776 fprintf(ctxt->output, "\n");
777 }
778 break;
779 case XML_ATTRIBUTE_NODE:
780 if (!ctxt->check)
781 xmlCtxtDumpSpaces(ctxt);
782 fprintf(ctxt->output, "Error, ATTRIBUTE found here\n");
783 break;
784 case XML_TEXT_NODE:
785 if (!ctxt->check) {
786 xmlCtxtDumpSpaces(ctxt);
787 if (node->name == (const xmlChar *) xmlStringTextNoenc)
788 fprintf(ctxt->output, "TEXT no enc\n");
789 else
790 fprintf(ctxt->output, "TEXT\n");
791 }
792 break;
793 case XML_CDATA_SECTION_NODE:
794 if (!ctxt->check) {
795 xmlCtxtDumpSpaces(ctxt);
796 fprintf(ctxt->output, "CDATA_SECTION\n");
797 }
798 break;
799 case XML_ENTITY_REF_NODE:
800 if (!ctxt->check) {
801 xmlCtxtDumpSpaces(ctxt);
802 fprintf(ctxt->output, "ENTITY_REF(%s)\n",
803 (char *) node->name);
804 }
805 break;
806 case XML_ENTITY_NODE:
807 if (!ctxt->check) {
808 xmlCtxtDumpSpaces(ctxt);
809 fprintf(ctxt->output, "ENTITY\n");
810 }
811 break;
812 case XML_PI_NODE:
813 if (!ctxt->check) {
814 xmlCtxtDumpSpaces(ctxt);
815 fprintf(ctxt->output, "PI %s\n", (char *) node->name);
816 }
817 break;
818 case XML_COMMENT_NODE:
819 if (!ctxt->check) {
820 xmlCtxtDumpSpaces(ctxt);
821 fprintf(ctxt->output, "COMMENT\n");
822 }
823 break;
824 case XML_DOCUMENT_NODE:
825 case XML_HTML_DOCUMENT_NODE:
826 if (!ctxt->check) {
827 xmlCtxtDumpSpaces(ctxt);
828 }
829 fprintf(ctxt->output, "PBM: DOCUMENT found here\n");
830 break;
831 case XML_DOCUMENT_TYPE_NODE:
832 if (!ctxt->check) {
833 xmlCtxtDumpSpaces(ctxt);
834 fprintf(ctxt->output, "DOCUMENT_TYPE\n");
835 }
836 break;
837 case XML_DOCUMENT_FRAG_NODE:
838 if (!ctxt->check) {
839 xmlCtxtDumpSpaces(ctxt);
840 fprintf(ctxt->output, "DOCUMENT_FRAG\n");
841 }
842 break;
843 case XML_NOTATION_NODE:
844 if (!ctxt->check) {
845 xmlCtxtDumpSpaces(ctxt);
846 fprintf(ctxt->output, "NOTATION\n");
847 }
848 break;
849 case XML_DTD_NODE:
850 xmlCtxtDumpDtdNode(ctxt, (xmlDtdPtr) node);
851 return;
852 case XML_ELEMENT_DECL:
853 xmlCtxtDumpElemDecl(ctxt, (xmlElementPtr) node);
854 return;
855 case XML_ATTRIBUTE_DECL:
856 xmlCtxtDumpAttrDecl(ctxt, (xmlAttributePtr) node);
857 return;
858 case XML_ENTITY_DECL:
859 xmlCtxtDumpEntityDecl(ctxt, (xmlEntityPtr) node);
860 return;
861 case XML_NAMESPACE_DECL:
862 xmlCtxtDumpNamespace(ctxt, (xmlNsPtr) node);
863 return;
864 case XML_XINCLUDE_START:
865 if (!ctxt->check) {
866 xmlCtxtDumpSpaces(ctxt);
867 fprintf(ctxt->output, "INCLUDE START\n");
868 }
869 return;
870 case XML_XINCLUDE_END:
871 if (!ctxt->check) {
872 xmlCtxtDumpSpaces(ctxt);
873 fprintf(ctxt->output, "INCLUDE END\n");
874 }
875 return;
876 default:
877 if (!ctxt->check)
878 xmlCtxtDumpSpaces(ctxt);
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000879 xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE,
880 "Unknown node type %d\n", node->type);
Daniel Veillard22cdb842004-10-04 14:09:17 +0000881 return;
882 }
883 if (node->doc == NULL) {
884 if (!ctxt->check) {
885 xmlCtxtDumpSpaces(ctxt);
886 }
887 fprintf(ctxt->output, "PBM: doc == NULL !!!\n");
888 }
889 ctxt->depth++;
890 if (node->nsDef != NULL)
891 xmlCtxtDumpNamespaceList(ctxt, node->nsDef);
892 if (node->properties != NULL)
893 xmlCtxtDumpAttrList(ctxt, node->properties);
894 if (node->type != XML_ENTITY_REF_NODE) {
895 if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
896 if (!ctxt->check) {
897 xmlCtxtDumpSpaces(ctxt);
898 fprintf(ctxt->output, "content=");
899 xmlCtxtDumpString(ctxt, node->content);
900 fprintf(ctxt->output, "\n");
901 }
902 }
903 } else {
904 xmlEntityPtr ent;
905
906 ent = xmlGetDocEntity(node->doc, node->name);
907 if (ent != NULL)
908 xmlCtxtDumpEntity(ctxt, ent);
909 }
910 ctxt->depth--;
911
912 /*
913 * Do a bit of checking
914 */
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000915 xmlCtxtGenericNodeCheck(ctxt, node);
Daniel Veillard22cdb842004-10-04 14:09:17 +0000916}
917
918/**
919 * xmlCtxtDumpNode:
920 * @output: the FILE * for the output
921 * @node: the node
922 * @depth: the indentation level.
923 *
924 * Dumps debug information for the element node, it is recursive
925 */
926static void
927xmlCtxtDumpNode(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
928{
929 if (node == NULL) {
930 if (!ctxt->check) {
931 xmlCtxtDumpSpaces(ctxt);
932 fprintf(ctxt->output, "node is NULL\n");
933 }
934 return;
935 }
936 xmlCtxtDumpOneNode(ctxt, node);
937 if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
938 ctxt->depth++;
939 xmlCtxtDumpNodeList(ctxt, node->children);
940 ctxt->depth--;
941 }
942}
943
944/**
945 * xmlCtxtDumpNodeList:
946 * @output: the FILE * for the output
947 * @node: the node list
948 * @depth: the indentation level.
949 *
950 * Dumps debug information for the list of element node, it is recursive
951 */
952static void
953xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
954{
955 while (node != NULL) {
956 xmlCtxtDumpNode(ctxt, node);
957 node = node->next;
958 }
959}
960
Daniel Veillard8de5c0b2004-10-07 13:14:19 +0000961static void
962xmlCtxtDumpDocHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
963{
964 if (doc == NULL) {
965 if (!ctxt->check)
966 fprintf(ctxt->output, "DOCUMENT == NULL !\n");
967 return;
968 }
969 ctxt->node = (xmlNodePtr) doc;
970
971 switch (doc->type) {
972 case XML_ELEMENT_NODE:
973 xmlDebugErr(ctxt, XML_CHECK_FOUND_ELEMENT,
974 "Misplaced ELEMENT node\n");
975 break;
976 case XML_ATTRIBUTE_NODE:
977 xmlDebugErr(ctxt, XML_CHECK_FOUND_ATTRIBUTE,
978 "Misplaced ATTRIBUTE node\n");
979 break;
980 case XML_TEXT_NODE:
981 xmlDebugErr(ctxt, XML_CHECK_FOUND_TEXT,
982 "Misplaced TEXT node\n");
983 break;
984 case XML_CDATA_SECTION_NODE:
985 xmlDebugErr(ctxt, XML_CHECK_FOUND_CDATA,
986 "Misplaced CDATA node\n");
987 break;
988 case XML_ENTITY_REF_NODE:
989 xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITYREF,
990 "Misplaced ENTITYREF node\n");
991 break;
992 case XML_ENTITY_NODE:
993 xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITY,
994 "Misplaced ENTITY node\n");
995 break;
996 case XML_PI_NODE:
997 xmlDebugErr(ctxt, XML_CHECK_FOUND_PI,
998 "Misplaced PI node\n");
999 break;
1000 case XML_COMMENT_NODE:
1001 xmlDebugErr(ctxt, XML_CHECK_FOUND_COMMENT,
1002 "Misplaced COMMENT node\n");
1003 break;
1004 case XML_DOCUMENT_NODE:
1005 if (!ctxt->check)
1006 fprintf(ctxt->output, "DOCUMENT\n");
1007 break;
1008 case XML_HTML_DOCUMENT_NODE:
1009 if (!ctxt->check)
1010 fprintf(ctxt->output, "HTML DOCUMENT\n");
1011 break;
1012 case XML_DOCUMENT_TYPE_NODE:
1013 xmlDebugErr(ctxt, XML_CHECK_FOUND_DOCTYPE,
1014 "Misplaced DOCTYPE node\n");
1015 break;
1016 case XML_DOCUMENT_FRAG_NODE:
1017 xmlDebugErr(ctxt, XML_CHECK_FOUND_FRAGMENT,
1018 "Misplaced FRAGMENT node\n");
1019 break;
1020 case XML_NOTATION_NODE:
1021 xmlDebugErr(ctxt, XML_CHECK_FOUND_NOTATION,
1022 "Misplaced NOTATION node\n");
1023 break;
1024 default:
1025 xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE,
1026 "Unknown node type %d\n", doc->type);
1027 }
1028}
Daniel Veillard22cdb842004-10-04 14:09:17 +00001029
1030/**
1031 * xmlCtxtDumpDocumentHead:
1032 * @output: the FILE * for the output
1033 * @doc: the document
1034 *
1035 * Dumps debug information cncerning the document, not recursive
1036 */
1037static void
1038xmlCtxtDumpDocumentHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1039{
Daniel Veillard8de5c0b2004-10-07 13:14:19 +00001040 xmlCtxtDumpDocHead(ctxt, doc);
Daniel Veillard22cdb842004-10-04 14:09:17 +00001041 if (!ctxt->check) {
1042 if (doc->name != NULL) {
1043 fprintf(ctxt->output, "name=");
1044 xmlCtxtDumpString(ctxt, BAD_CAST doc->name);
1045 fprintf(ctxt->output, "\n");
1046 }
1047 if (doc->version != NULL) {
1048 fprintf(ctxt->output, "version=");
1049 xmlCtxtDumpString(ctxt, doc->version);
1050 fprintf(ctxt->output, "\n");
1051 }
1052 if (doc->encoding != NULL) {
1053 fprintf(ctxt->output, "encoding=");
1054 xmlCtxtDumpString(ctxt, doc->encoding);
1055 fprintf(ctxt->output, "\n");
1056 }
1057 if (doc->URL != NULL) {
1058 fprintf(ctxt->output, "URL=");
1059 xmlCtxtDumpString(ctxt, doc->URL);
1060 fprintf(ctxt->output, "\n");
1061 }
1062 if (doc->standalone)
1063 fprintf(ctxt->output, "standalone=true\n");
1064 }
1065 if (doc->oldNs != NULL)
1066 xmlCtxtDumpNamespaceList(ctxt, doc->oldNs);
1067}
1068
1069/**
1070 * xmlCtxtDumpDocument:
1071 * @output: the FILE * for the output
1072 * @doc: the document
1073 *
1074 * Dumps debug information for the document, it's recursive
1075 */
1076static void
1077xmlCtxtDumpDocument(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1078{
1079 if (doc == NULL) {
1080 if (!ctxt->check)
1081 fprintf(ctxt->output, "DOCUMENT == NULL !\n");
1082 return;
1083 }
1084 xmlCtxtDumpDocumentHead(ctxt, doc);
1085 if (((doc->type == XML_DOCUMENT_NODE) ||
1086 (doc->type == XML_HTML_DOCUMENT_NODE))
1087 && (doc->children != NULL)) {
1088 ctxt->depth++;
1089 xmlCtxtDumpNodeList(ctxt, doc->children);
1090 ctxt->depth--;
1091 }
1092}
1093
1094static void
1095xmlCtxtDumpEntityCallback(xmlEntityPtr cur, xmlDebugCtxtPtr ctxt)
1096{
1097 if (cur == NULL) {
1098 if (!ctxt->check)
1099 fprintf(ctxt->output, "Entity is NULL");
1100 return;
1101 }
1102 if (!ctxt->check) {
1103 fprintf(ctxt->output, "%s : ", (char *) cur->name);
1104 switch (cur->etype) {
1105 case XML_INTERNAL_GENERAL_ENTITY:
1106 fprintf(ctxt->output, "INTERNAL GENERAL, ");
1107 break;
1108 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1109 fprintf(ctxt->output, "EXTERNAL PARSED, ");
1110 break;
1111 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1112 fprintf(ctxt->output, "EXTERNAL UNPARSED, ");
1113 break;
1114 case XML_INTERNAL_PARAMETER_ENTITY:
1115 fprintf(ctxt->output, "INTERNAL PARAMETER, ");
1116 break;
1117 case XML_EXTERNAL_PARAMETER_ENTITY:
1118 fprintf(ctxt->output, "EXTERNAL PARAMETER, ");
1119 break;
1120 default:
Daniel Veillard8de5c0b2004-10-07 13:14:19 +00001121 xmlDebugErr2(ctxt, XML_CHECK_ENTITY_TYPE,
1122 "Unknown entity type %d\n", cur->etype);
Daniel Veillard22cdb842004-10-04 14:09:17 +00001123 }
1124 if (cur->ExternalID != NULL)
1125 fprintf(ctxt->output, "ID \"%s\"", (char *) cur->ExternalID);
1126 if (cur->SystemID != NULL)
1127 fprintf(ctxt->output, "SYSTEM \"%s\"", (char *) cur->SystemID);
1128 if (cur->orig != NULL)
1129 fprintf(ctxt->output, "\n orig \"%s\"", (char *) cur->orig);
1130 if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL))
1131 fprintf(ctxt->output, "\n content \"%s\"",
1132 (char *) cur->content);
1133 fprintf(ctxt->output, "\n");
1134 }
1135}
1136
1137/**
1138 * xmlCtxtDumpEntities:
1139 * @output: the FILE * for the output
1140 * @doc: the document
1141 *
1142 * Dumps debug information for all the entities in use by the document
1143 */
1144static void
1145xmlCtxtDumpEntities(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
1146{
Daniel Veillard8de5c0b2004-10-07 13:14:19 +00001147 xmlCtxtDumpDocHead(ctxt, doc);
Daniel Veillard22cdb842004-10-04 14:09:17 +00001148 if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
1149 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1150 doc->intSubset->entities;
1151
1152 if (!ctxt->check)
1153 fprintf(ctxt->output, "Entities in internal subset\n");
1154 xmlHashScan(table, (xmlHashScanner) xmlCtxtDumpEntityCallback,
1155 ctxt);
1156 } else
1157 fprintf(ctxt->output, "No entities in internal subset\n");
1158 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
1159 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1160 doc->extSubset->entities;
1161
1162 if (!ctxt->check)
1163 fprintf(ctxt->output, "Entities in external subset\n");
1164 xmlHashScan(table, (xmlHashScanner) xmlCtxtDumpEntityCallback,
1165 ctxt);
1166 } else if (!ctxt->check)
1167 fprintf(ctxt->output, "No entities in external subset\n");
1168}
1169
1170/**
1171 * xmlCtxtDumpDTD:
1172 * @output: the FILE * for the output
1173 * @dtd: the DTD
1174 *
1175 * Dumps debug information for the DTD
1176 */
1177static void
1178xmlCtxtDumpDTD(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd)
1179{
1180 if (dtd == NULL) {
1181 if (!ctxt->check)
1182 fprintf(ctxt->output, "DTD is NULL\n");
1183 return;
1184 }
Daniel Veillard8de5c0b2004-10-07 13:14:19 +00001185 xmlCtxtDumpDtdNode(ctxt, dtd);
Daniel Veillard22cdb842004-10-04 14:09:17 +00001186 if (dtd->children == NULL)
1187 fprintf(ctxt->output, " DTD is empty\n");
1188 else {
1189 ctxt->depth++;
1190 xmlCtxtDumpNodeList(ctxt, dtd->children);
1191 ctxt->depth--;
1192 }
1193}
Daniel Veillard8de5c0b2004-10-07 13:14:19 +00001194
Daniel Veillard22cdb842004-10-04 14:09:17 +00001195/************************************************************************
1196 * *
Daniel Veillard8de5c0b2004-10-07 13:14:19 +00001197 * Public entry points for dump *
Daniel Veillard22cdb842004-10-04 14:09:17 +00001198 * *
1199 ************************************************************************/
1200
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001201/**
1202 * xmlDebugDumpString:
1203 * @output: the FILE * for the output
1204 * @str: the string
1205 *
1206 * Dumps informations about the string, shorten it if necessary
1207 */
1208void
1209xmlDebugDumpString(FILE * output, const xmlChar * str)
1210{
Owen Taylor3473f882001-02-23 17:55:21 +00001211 int i;
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001212
Daniel Veillard7db38712002-02-07 16:39:11 +00001213 if (output == NULL)
1214 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +00001215 if (str == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001216 fprintf(output, "(NULL)");
1217 return;
Owen Taylor3473f882001-02-23 17:55:21 +00001218 }
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001219 for (i = 0; i < 40; i++)
1220 if (str[i] == 0)
1221 return;
William M. Brack76e95df2003-10-18 16:20:14 +00001222 else if (IS_BLANK_CH(str[i]))
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001223 fputc(' ', output);
1224 else if (str[i] >= 0x80)
1225 fprintf(output, "#%X", str[i]);
1226 else
1227 fputc(str[i], output);
Owen Taylor3473f882001-02-23 17:55:21 +00001228 fprintf(output, "...");
1229}
1230
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001231/**
1232 * xmlDebugDumpAttr:
1233 * @output: the FILE * for the output
1234 * @attr: the attribute
1235 * @depth: the indentation level.
1236 *
1237 * Dumps debug information for the attribute
1238 */
1239void
1240xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
Daniel Veillard22cdb842004-10-04 14:09:17 +00001241 xmlDebugCtxt ctxt;
Owen Taylor3473f882001-02-23 17:55:21 +00001242
Daniel Veillard22cdb842004-10-04 14:09:17 +00001243 xmlCtxtDumpInitCtxt(&ctxt);
1244 ctxt.output = output;
1245 ctxt.depth = depth;
1246 xmlCtxtDumpAttr(&ctxt, attr);
Daniel Veillard76821142004-10-09 20:39:04 +00001247 xmlCtxtDumpCleanCtxt(&ctxt);
Daniel Veillard22cdb842004-10-04 14:09:17 +00001248}
Owen Taylor3473f882001-02-23 17:55:21 +00001249
Owen Taylor3473f882001-02-23 17:55:21 +00001250
Daniel Veillard22cdb842004-10-04 14:09:17 +00001251/**
1252 * xmlDebugDumpEntities:
1253 * @output: the FILE * for the output
1254 * @doc: the document
1255 *
1256 * Dumps debug information for all the entities in use by the document
1257 */
1258void
1259xmlDebugDumpEntities(FILE * output, xmlDocPtr doc)
1260{
1261 xmlDebugCtxt ctxt;
1262
1263 xmlCtxtDumpInitCtxt(&ctxt);
1264 ctxt.output = output;
1265 xmlCtxtDumpEntities(&ctxt, doc);
Daniel Veillard76821142004-10-09 20:39:04 +00001266 xmlCtxtDumpCleanCtxt(&ctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001267}
1268
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001269/**
1270 * xmlDebugDumpAttrList:
1271 * @output: the FILE * for the output
1272 * @attr: the attribute list
1273 * @depth: the indentation level.
1274 *
1275 * Dumps debug information for the attribute list
1276 */
1277void
1278xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth)
1279{
Daniel Veillard22cdb842004-10-04 14:09:17 +00001280 xmlDebugCtxt ctxt;
1281
1282 xmlCtxtDumpInitCtxt(&ctxt);
1283 ctxt.output = output;
1284 ctxt.depth = depth;
1285 xmlCtxtDumpAttrList(&ctxt, attr);
Daniel Veillard76821142004-10-09 20:39:04 +00001286 xmlCtxtDumpCleanCtxt(&ctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001287}
1288
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001289/**
1290 * xmlDebugDumpOneNode:
1291 * @output: the FILE * for the output
1292 * @node: the node
1293 * @depth: the indentation level.
1294 *
1295 * Dumps debug information for the element node, it is not recursive
1296 */
1297void
1298xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth)
1299{
Daniel Veillard22cdb842004-10-04 14:09:17 +00001300 xmlDebugCtxt ctxt;
Owen Taylor3473f882001-02-23 17:55:21 +00001301
Daniel Veillard22cdb842004-10-04 14:09:17 +00001302 xmlCtxtDumpInitCtxt(&ctxt);
1303 ctxt.output = output;
1304 ctxt.depth = depth;
1305 xmlCtxtDumpOneNode(&ctxt, node);
Daniel Veillard76821142004-10-09 20:39:04 +00001306 xmlCtxtDumpCleanCtxt(&ctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001307}
1308
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001309/**
1310 * xmlDebugDumpNode:
1311 * @output: the FILE * for the output
1312 * @node: the node
1313 * @depth: the indentation level.
1314 *
1315 * Dumps debug information for the element node, it is recursive
1316 */
1317void
1318xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth)
1319{
Daniel Veillard22cdb842004-10-04 14:09:17 +00001320 xmlDebugCtxt ctxt;
1321
Daniel Veillard7db38712002-02-07 16:39:11 +00001322 if (output == NULL)
1323 output = stdout;
Daniel Veillard22cdb842004-10-04 14:09:17 +00001324 xmlCtxtDumpInitCtxt(&ctxt);
1325 ctxt.output = output;
1326 ctxt.depth = depth;
1327 xmlCtxtDumpNode(&ctxt, node);
Daniel Veillard76821142004-10-09 20:39:04 +00001328 xmlCtxtDumpCleanCtxt(&ctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001329}
1330
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001331/**
1332 * xmlDebugDumpNodeList:
1333 * @output: the FILE * for the output
1334 * @node: the node list
1335 * @depth: the indentation level.
1336 *
1337 * Dumps debug information for the list of element node, it is recursive
1338 */
1339void
1340xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth)
1341{
Daniel Veillard22cdb842004-10-04 14:09:17 +00001342 xmlDebugCtxt ctxt;
1343
Daniel Veillard7db38712002-02-07 16:39:11 +00001344 if (output == NULL)
1345 output = stdout;
Daniel Veillard22cdb842004-10-04 14:09:17 +00001346 xmlCtxtDumpInitCtxt(&ctxt);
1347 ctxt.output = output;
1348 ctxt.depth = depth;
1349 xmlCtxtDumpNodeList(&ctxt, node);
Daniel Veillard76821142004-10-09 20:39:04 +00001350 xmlCtxtDumpCleanCtxt(&ctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001351}
1352
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001353/**
1354 * xmlDebugDumpDocumentHead:
1355 * @output: the FILE * for the output
1356 * @doc: the document
1357 *
1358 * Dumps debug information cncerning the document, not recursive
1359 */
1360void
1361xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc)
1362{
Daniel Veillard22cdb842004-10-04 14:09:17 +00001363 xmlDebugCtxt ctxt;
Owen Taylor3473f882001-02-23 17:55:21 +00001364
Daniel Veillard22cdb842004-10-04 14:09:17 +00001365 if (output == NULL)
1366 output = stdout;
1367 xmlCtxtDumpInitCtxt(&ctxt);
1368 ctxt.output = output;
1369 xmlCtxtDumpDocumentHead(&ctxt, doc);
Daniel Veillard76821142004-10-09 20:39:04 +00001370 xmlCtxtDumpCleanCtxt(&ctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001371}
1372
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001373/**
1374 * xmlDebugDumpDocument:
1375 * @output: the FILE * for the output
1376 * @doc: the document
1377 *
1378 * Dumps debug information for the document, it's recursive
1379 */
1380void
1381xmlDebugDumpDocument(FILE * output, xmlDocPtr doc)
1382{
Daniel Veillard22cdb842004-10-04 14:09:17 +00001383 xmlDebugCtxt ctxt;
1384
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001385 if (output == NULL)
Daniel Veillard22cdb842004-10-04 14:09:17 +00001386 output = stdout;
1387 xmlCtxtDumpInitCtxt(&ctxt);
1388 ctxt.output = output;
1389 xmlCtxtDumpDocument(&ctxt, doc);
Daniel Veillard76821142004-10-09 20:39:04 +00001390 xmlCtxtDumpCleanCtxt(&ctxt);
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001391}
Owen Taylor3473f882001-02-23 17:55:21 +00001392
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001393/**
1394 * xmlDebugDumpDTD:
1395 * @output: the FILE * for the output
1396 * @dtd: the DTD
1397 *
1398 * Dumps debug information for the DTD
1399 */
1400void
1401xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd)
1402{
Daniel Veillard22cdb842004-10-04 14:09:17 +00001403 xmlDebugCtxt ctxt;
1404
Daniel Veillard7db38712002-02-07 16:39:11 +00001405 if (output == NULL)
1406 output = stdout;
Daniel Veillard22cdb842004-10-04 14:09:17 +00001407 xmlCtxtDumpInitCtxt(&ctxt);
1408 ctxt.output = output;
1409 xmlCtxtDumpDTD(&ctxt, dtd);
Daniel Veillard76821142004-10-09 20:39:04 +00001410 xmlCtxtDumpCleanCtxt(&ctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001411}
1412
Daniel Veillard22cdb842004-10-04 14:09:17 +00001413/************************************************************************
1414 * *
Daniel Veillard8de5c0b2004-10-07 13:14:19 +00001415 * Public entry points for checkings *
1416 * *
1417 ************************************************************************/
1418
1419/**
1420 * xmlDebugCheckDocument:
1421 * @output: the FILE * for the output
1422 * @doc: the document
1423 *
1424 * Check the document for potential content problems, and output
1425 * the errors to @output
1426 *
1427 * Returns the number of errors found
1428 */
1429int
1430xmlDebugCheckDocument(FILE * output, xmlDocPtr doc)
1431{
1432 xmlDebugCtxt ctxt;
1433
1434 if (output == NULL)
1435 output = stdout;
1436 xmlCtxtDumpInitCtxt(&ctxt);
1437 ctxt.output = output;
1438 ctxt.check = 1;
1439 xmlCtxtDumpDocument(&ctxt, doc);
Daniel Veillard76821142004-10-09 20:39:04 +00001440 xmlCtxtDumpCleanCtxt(&ctxt);
Daniel Veillard8de5c0b2004-10-07 13:14:19 +00001441 return(ctxt.errors);
1442}
1443
1444/************************************************************************
1445 * *
Daniel Veillard22cdb842004-10-04 14:09:17 +00001446 * Helpers for Shell *
1447 * *
1448 ************************************************************************/
Owen Taylor3473f882001-02-23 17:55:21 +00001449
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001450/**
1451 * xmlLsCountNode:
1452 * @node: the node to count
1453 *
1454 * Count the children of @node.
1455 *
1456 * Returns the number of children of @node.
1457 */
1458int
1459xmlLsCountNode(xmlNodePtr node) {
Owen Taylor3473f882001-02-23 17:55:21 +00001460 int ret = 0;
1461 xmlNodePtr list = NULL;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001462
1463 if (node == NULL)
1464 return(0);
Owen Taylor3473f882001-02-23 17:55:21 +00001465
1466 switch (node->type) {
1467 case XML_ELEMENT_NODE:
1468 list = node->children;
1469 break;
1470 case XML_DOCUMENT_NODE:
1471 case XML_HTML_DOCUMENT_NODE:
Daniel Veillardeae522a2001-04-23 13:41:34 +00001472#ifdef LIBXML_DOCB_ENABLED
1473 case XML_DOCB_DOCUMENT_NODE:
Owen Taylor3473f882001-02-23 17:55:21 +00001474#endif
1475 list = ((xmlDocPtr) node)->children;
1476 break;
1477 case XML_ATTRIBUTE_NODE:
1478 list = ((xmlAttrPtr) node)->children;
1479 break;
1480 case XML_TEXT_NODE:
1481 case XML_CDATA_SECTION_NODE:
1482 case XML_PI_NODE:
1483 case XML_COMMENT_NODE:
1484 if (node->content != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001485 ret = xmlStrlen(node->content);
Owen Taylor3473f882001-02-23 17:55:21 +00001486 }
1487 break;
1488 case XML_ENTITY_REF_NODE:
1489 case XML_DOCUMENT_TYPE_NODE:
1490 case XML_ENTITY_NODE:
1491 case XML_DOCUMENT_FRAG_NODE:
1492 case XML_NOTATION_NODE:
1493 case XML_DTD_NODE:
1494 case XML_ELEMENT_DECL:
1495 case XML_ATTRIBUTE_DECL:
1496 case XML_ENTITY_DECL:
1497 case XML_NAMESPACE_DECL:
1498 case XML_XINCLUDE_START:
1499 case XML_XINCLUDE_END:
1500 ret = 1;
1501 break;
1502 }
1503 for (;list != NULL;ret++)
1504 list = list->next;
1505 return(ret);
1506}
1507
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001508/**
1509 * xmlLsOneNode:
1510 * @output: the FILE * for the output
1511 * @node: the node to dump
1512 *
1513 * Dump to @output the type and name of @node.
1514 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001515void
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001516xmlLsOneNode(FILE *output, xmlNodePtr node) {
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001517 if (node == NULL) {
1518 fprintf(output, "NULL\n");
1519 return;
1520 }
Owen Taylor3473f882001-02-23 17:55:21 +00001521 switch (node->type) {
1522 case XML_ELEMENT_NODE:
1523 fprintf(output, "-");
1524 break;
1525 case XML_ATTRIBUTE_NODE:
1526 fprintf(output, "a");
1527 break;
1528 case XML_TEXT_NODE:
1529 fprintf(output, "t");
1530 break;
1531 case XML_CDATA_SECTION_NODE:
Daniel Veillard75be0132002-03-13 10:03:35 +00001532 fprintf(output, "C");
Owen Taylor3473f882001-02-23 17:55:21 +00001533 break;
1534 case XML_ENTITY_REF_NODE:
1535 fprintf(output, "e");
1536 break;
1537 case XML_ENTITY_NODE:
1538 fprintf(output, "E");
1539 break;
1540 case XML_PI_NODE:
1541 fprintf(output, "p");
1542 break;
1543 case XML_COMMENT_NODE:
1544 fprintf(output, "c");
1545 break;
1546 case XML_DOCUMENT_NODE:
1547 fprintf(output, "d");
1548 break;
1549 case XML_HTML_DOCUMENT_NODE:
1550 fprintf(output, "h");
1551 break;
1552 case XML_DOCUMENT_TYPE_NODE:
1553 fprintf(output, "T");
1554 break;
1555 case XML_DOCUMENT_FRAG_NODE:
1556 fprintf(output, "F");
1557 break;
1558 case XML_NOTATION_NODE:
1559 fprintf(output, "N");
1560 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001561 case XML_NAMESPACE_DECL:
1562 fprintf(output, "n");
1563 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001564 default:
1565 fprintf(output, "?");
1566 }
Daniel Veillarde6a55192002-01-14 17:11:53 +00001567 if (node->type != XML_NAMESPACE_DECL) {
1568 if (node->properties != NULL)
1569 fprintf(output, "a");
1570 else
1571 fprintf(output, "-");
1572 if (node->nsDef != NULL)
1573 fprintf(output, "n");
1574 else
1575 fprintf(output, "-");
1576 }
Owen Taylor3473f882001-02-23 17:55:21 +00001577
1578 fprintf(output, " %8d ", xmlLsCountNode(node));
1579
1580 switch (node->type) {
1581 case XML_ELEMENT_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_ATTRIBUTE_NODE:
1586 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001587 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001588 break;
1589 case XML_TEXT_NODE:
1590 if (node->content != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001591 xmlDebugDumpString(output, node->content);
Owen Taylor3473f882001-02-23 17:55:21 +00001592 }
1593 break;
1594 case XML_CDATA_SECTION_NODE:
1595 break;
1596 case XML_ENTITY_REF_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_ENTITY_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_PI_NODE:
1605 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001606 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001607 break;
1608 case XML_COMMENT_NODE:
1609 break;
1610 case XML_DOCUMENT_NODE:
1611 break;
1612 case XML_HTML_DOCUMENT_NODE:
1613 break;
1614 case XML_DOCUMENT_TYPE_NODE:
1615 break;
1616 case XML_DOCUMENT_FRAG_NODE:
1617 break;
1618 case XML_NOTATION_NODE:
1619 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001620 case XML_NAMESPACE_DECL: {
1621 xmlNsPtr ns = (xmlNsPtr) node;
1622
1623 if (ns->prefix == NULL)
William M. Brack13dfa872004-09-18 04:52:08 +00001624 fprintf(output, "default -> %s", (char *)ns->href);
Daniel Veillarde6a55192002-01-14 17:11:53 +00001625 else
William M. Brack13dfa872004-09-18 04:52:08 +00001626 fprintf(output, "%s -> %s", (char *)ns->prefix,
1627 (char *)ns->href);
Daniel Veillarde6a55192002-01-14 17:11:53 +00001628 break;
1629 }
Owen Taylor3473f882001-02-23 17:55:21 +00001630 default:
1631 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001632 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001633 }
1634 fprintf(output, "\n");
1635}
1636
Daniel Veillard78d12092001-10-11 09:12:24 +00001637/**
1638 * xmlBoolToText:
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001639 * @boolval: a bool to turn into text
Daniel Veillard78d12092001-10-11 09:12:24 +00001640 *
1641 * Convenient way to turn bool into text
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001642 *
1643 * Returns a pointer to either "True" or "False"
1644 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001645const char *
Daniel Veillardebd38c52001-11-01 08:38:12 +00001646xmlBoolToText(int boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001647{
Daniel Veillardebd38c52001-11-01 08:38:12 +00001648 if (boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001649 return("True");
1650 else
1651 return("False");
1652}
1653
Owen Taylor3473f882001-02-23 17:55:21 +00001654/****************************************************************
1655 * *
1656 * The XML shell related functions *
1657 * *
1658 ****************************************************************/
1659
Daniel Veillard78d12092001-10-11 09:12:24 +00001660
1661
Owen Taylor3473f882001-02-23 17:55:21 +00001662/*
1663 * TODO: Improvement/cleanups for the XML shell
1664 * - allow to shell out an editor on a subpart
1665 * - cleanup function registrations (with help) and calling
1666 * - provide registration routines
1667 */
1668
1669/**
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001670 * xmlShellPrintXPathError:
Daniel Veillard78d12092001-10-11 09:12:24 +00001671 * @errorType: valid xpath error id
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001672 * @arg: the argument that cause xpath to fail
Daniel Veillard78d12092001-10-11 09:12:24 +00001673 *
1674 * Print the xpath error to libxml default error channel
1675 */
1676void
1677xmlShellPrintXPathError(int errorType, const char *arg)
1678{
1679 const char *default_arg = "Result";
1680
1681 if (!arg)
1682 arg = default_arg;
1683
1684 switch (errorType) {
1685 case XPATH_UNDEFINED:
1686 xmlGenericError(xmlGenericErrorContext,
1687 "%s: no such node\n", arg);
1688 break;
1689
1690 case XPATH_BOOLEAN:
1691 xmlGenericError(xmlGenericErrorContext,
1692 "%s is a Boolean\n", arg);
1693 break;
1694 case XPATH_NUMBER:
1695 xmlGenericError(xmlGenericErrorContext,
1696 "%s is a number\n", arg);
1697 break;
1698 case XPATH_STRING:
1699 xmlGenericError(xmlGenericErrorContext,
1700 "%s is a string\n", arg);
1701 break;
1702 case XPATH_POINT:
1703 xmlGenericError(xmlGenericErrorContext,
1704 "%s is a point\n", arg);
1705 break;
1706 case XPATH_RANGE:
1707 xmlGenericError(xmlGenericErrorContext,
1708 "%s is a range\n", arg);
1709 break;
1710 case XPATH_LOCATIONSET:
1711 xmlGenericError(xmlGenericErrorContext,
1712 "%s is a range\n", arg);
1713 break;
1714 case XPATH_USERS:
1715 xmlGenericError(xmlGenericErrorContext,
1716 "%s is user-defined\n", arg);
1717 break;
1718 case XPATH_XSLT_TREE:
1719 xmlGenericError(xmlGenericErrorContext,
1720 "%s is an XSLT value tree\n", arg);
1721 break;
1722 }
1723 xmlGenericError(xmlGenericErrorContext,
1724 "Try casting the result string function (xpath builtin)\n",
1725 arg);
1726}
1727
1728
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001729#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001730/**
Daniel Veillard321be0c2002-10-08 21:26:42 +00001731 * xmlShellPrintNodeCtxt:
1732 * @ctxt : a non-null shell context
1733 * @node : a non-null node to print to the output FILE
Daniel Veillard78d12092001-10-11 09:12:24 +00001734 *
Daniel Veillard321be0c2002-10-08 21:26:42 +00001735 * Print node to the output FILE
1736 */
1737static void
1738xmlShellPrintNodeCtxt(xmlShellCtxtPtr ctxt,xmlNodePtr node)
1739{
Daniel Veillard01992e02002-10-09 10:20:30 +00001740 FILE *fp;
1741
1742 if (!node)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001743 return;
Daniel Veillard01992e02002-10-09 10:20:30 +00001744 if (ctxt == NULL)
1745 fp = stdout;
1746 else
1747 fp = ctxt->output;
Daniel Veillard321be0c2002-10-08 21:26:42 +00001748
1749 if (node->type == XML_DOCUMENT_NODE)
Daniel Veillard01992e02002-10-09 10:20:30 +00001750 xmlDocDump(fp, (xmlDocPtr) node);
Daniel Veillard321be0c2002-10-08 21:26:42 +00001751 else if (node->type == XML_ATTRIBUTE_NODE)
Daniel Veillard01992e02002-10-09 10:20:30 +00001752 xmlDebugDumpAttrList(fp, (xmlAttrPtr) node, 0);
Daniel Veillard321be0c2002-10-08 21:26:42 +00001753 else
Daniel Veillard01992e02002-10-09 10:20:30 +00001754 xmlElemDump(fp, node->doc, node);
Daniel Veillard321be0c2002-10-08 21:26:42 +00001755
Daniel Veillard01992e02002-10-09 10:20:30 +00001756 fprintf(fp, "\n");
Daniel Veillard321be0c2002-10-08 21:26:42 +00001757}
1758
1759/**
1760 * xmlShellPrintNode:
1761 * @node : a non-null node to print to the output FILE
1762 *
1763 * Print node to the output FILE
Daniel Veillard78d12092001-10-11 09:12:24 +00001764 */
1765void
1766xmlShellPrintNode(xmlNodePtr node)
1767{
Daniel Veillard321be0c2002-10-08 21:26:42 +00001768 xmlShellPrintNodeCtxt(NULL, node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001769}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001770#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001771
Daniel Veillard78d12092001-10-11 09:12:24 +00001772/**
Daniel Veillard321be0c2002-10-08 21:26:42 +00001773 * xmlShellPrintXPathResultCtxt:
1774 * @ctxt: a valid shell context
Daniel Veillard9d06d302002-01-22 18:15:52 +00001775 * @list: a valid result generated by an xpath evaluation
Daniel Veillard78d12092001-10-11 09:12:24 +00001776 *
Daniel Veillard321be0c2002-10-08 21:26:42 +00001777 * Prints result to the output FILE
Daniel Veillard78d12092001-10-11 09:12:24 +00001778 */
Daniel Veillard321be0c2002-10-08 21:26:42 +00001779static void
1780xmlShellPrintXPathResultCtxt(xmlShellCtxtPtr ctxt,xmlXPathObjectPtr list)
Daniel Veillard78d12092001-10-11 09:12:24 +00001781{
Daniel Veillard321be0c2002-10-08 21:26:42 +00001782 if (!ctxt)
1783 return;
Daniel Veillard78d12092001-10-11 09:12:24 +00001784
1785 if (list != NULL) {
1786 switch (list->type) {
1787 case XPATH_NODESET:{
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001788#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001789 int indx;
1790
1791 if (list->nodesetval) {
1792 for (indx = 0; indx < list->nodesetval->nodeNr;
1793 indx++) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001794 xmlShellPrintNodeCtxt(ctxt,
1795 list->nodesetval->nodeTab[indx]);
Daniel Veillard78d12092001-10-11 09:12:24 +00001796 }
1797 } else {
1798 xmlGenericError(xmlGenericErrorContext,
1799 "Empty node set\n");
1800 }
1801 break;
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001802#else
1803 xmlGenericError(xmlGenericErrorContext,
1804 "Node set\n");
1805#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001806 }
1807 case XPATH_BOOLEAN:
1808 xmlGenericError(xmlGenericErrorContext,
1809 "Is a Boolean:%s\n",
1810 xmlBoolToText(list->boolval));
1811 break;
1812 case XPATH_NUMBER:
1813 xmlGenericError(xmlGenericErrorContext,
1814 "Is a number:%0g\n", list->floatval);
1815 break;
1816 case XPATH_STRING:
1817 xmlGenericError(xmlGenericErrorContext,
1818 "Is a string:%s\n", list->stringval);
1819 break;
1820
1821 default:
1822 xmlShellPrintXPathError(list->type, NULL);
1823 }
1824 }
1825}
1826
1827/**
Daniel Veillard321be0c2002-10-08 21:26:42 +00001828 * xmlShellPrintXPathResult:
1829 * @list: a valid result generated by an xpath evaluation
1830 *
1831 * Prints result to the output FILE
1832 */
1833void
1834xmlShellPrintXPathResult(xmlXPathObjectPtr list)
1835{
1836 xmlShellPrintXPathResultCtxt(NULL, list);
1837}
1838
1839/**
Owen Taylor3473f882001-02-23 17:55:21 +00001840 * xmlShellList:
1841 * @ctxt: the shell context
1842 * @arg: unused
1843 * @node: a node
1844 * @node2: unused
1845 *
1846 * Implements the XML shell function "ls"
1847 * Does an Unix like listing of the given node (like a directory)
1848 *
1849 * Returns 0
1850 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001851int
Daniel Veillard321be0c2002-10-08 21:26:42 +00001852xmlShellList(xmlShellCtxtPtr ctxt,
Daniel Veillard78d12092001-10-11 09:12:24 +00001853 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1854 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1855{
Owen Taylor3473f882001-02-23 17:55:21 +00001856 xmlNodePtr cur;
Daniel Veillard321be0c2002-10-08 21:26:42 +00001857 if (!ctxt)
1858 return (0);
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001859 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001860 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001861 return (0);
1862 }
Owen Taylor3473f882001-02-23 17:55:21 +00001863 if ((node->type == XML_DOCUMENT_NODE) ||
1864 (node->type == XML_HTML_DOCUMENT_NODE)) {
1865 cur = ((xmlDocPtr) node)->children;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001866 } else if (node->type == XML_NAMESPACE_DECL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001867 xmlLsOneNode(ctxt->output, node);
Daniel Veillarde6a55192002-01-14 17:11:53 +00001868 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001869 } else if (node->children != NULL) {
1870 cur = node->children;
1871 } else {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001872 xmlLsOneNode(ctxt->output, node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001873 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001874 }
1875 while (cur != NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001876 xmlLsOneNode(ctxt->output, cur);
Daniel Veillard78d12092001-10-11 09:12:24 +00001877 cur = cur->next;
Owen Taylor3473f882001-02-23 17:55:21 +00001878 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001879 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001880}
1881
1882/**
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001883 * xmlShellBase:
1884 * @ctxt: the shell context
1885 * @arg: unused
1886 * @node: a node
1887 * @node2: unused
1888 *
1889 * Implements the XML shell function "base"
1890 * dumps the current XML base of the node
1891 *
1892 * Returns 0
1893 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001894int
Daniel Veillard321be0c2002-10-08 21:26:42 +00001895xmlShellBase(xmlShellCtxtPtr ctxt,
Daniel Veillard78d12092001-10-11 09:12:24 +00001896 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1897 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1898{
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001899 xmlChar *base;
Daniel Veillard321be0c2002-10-08 21:26:42 +00001900 if (!ctxt)
1901 return 0;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001902 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001903 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001904 return (0);
1905 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001906
1907 base = xmlNodeGetBase(node->doc, node);
1908
1909 if (base == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001910 fprintf(ctxt->output, " No base found !!!\n");
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001911 } else {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001912 fprintf(ctxt->output, "%s\n", base);
Daniel Veillard78d12092001-10-11 09:12:24 +00001913 xmlFree(base);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001914 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001915 return (0);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001916}
1917
Daniel Veillardb34321c2004-03-04 17:09:47 +00001918#ifdef LIBXML_TREE_ENABLED
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001919/**
Daniel Veillardcfa0d812002-01-17 08:46:58 +00001920 * xmlShellSetBase:
1921 * @ctxt: the shell context
1922 * @arg: the new base
1923 * @node: a node
1924 * @node2: unused
1925 *
1926 * Implements the XML shell function "setbase"
1927 * change the current XML base of the node
1928 *
1929 * Returns 0
1930 */
1931static int
1932xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1933 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1934 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1935{
1936 xmlNodeSetBase(node, (xmlChar*) arg);
1937 return (0);
1938}
Daniel Veillard2156d432004-03-04 15:59:36 +00001939#endif
Daniel Veillardcfa0d812002-01-17 08:46:58 +00001940
Daniel Veillardbbaa9972004-06-16 14:08:33 +00001941#ifdef LIBXML_XPATH_ENABLED
1942/**
1943 * xmlShellRegisterNamespace:
1944 * @ctxt: the shell context
1945 * @arg: a string in prefix=nsuri format
1946 * @node: unused
1947 * @node2: unused
1948 *
1949 * Implements the XML shell function "setns"
1950 * register/unregister a prefix=namespace pair
1951 * on the XPath context
1952 *
1953 * Returns 0 on success and a negative value otherwise.
1954 */
1955static int
1956xmlShellRegisterNamespace(xmlShellCtxtPtr ctxt, char *arg,
1957 xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1958{
1959 xmlChar* nsListDup;
1960 xmlChar* prefix;
1961 xmlChar* href;
1962 xmlChar* next;
1963
1964 nsListDup = xmlStrdup((xmlChar *) arg);
1965 next = nsListDup;
1966 while(next != NULL) {
1967 /* skip spaces */
1968 /*while((*next) == ' ') next++;*/
1969 if((*next) == '\0') break;
1970
1971 /* find prefix */
1972 prefix = next;
1973 next = (xmlChar*)xmlStrchr(next, '=');
1974 if(next == NULL) {
1975 fprintf(ctxt->output, "setns: prefix=[nsuri] required\n");
1976 xmlFree(nsListDup);
1977 return(-1);
1978 }
1979 *(next++) = '\0';
1980
1981 /* find href */
1982 href = next;
1983 next = (xmlChar*)xmlStrchr(next, ' ');
1984 if(next != NULL) {
1985 *(next++) = '\0';
1986 }
1987
1988 /* do register namespace */
1989 if(xmlXPathRegisterNs(ctxt->pctxt, prefix, href) != 0) {
1990 fprintf(ctxt->output,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", prefix, href);
1991 xmlFree(nsListDup);
1992 return(-1);
1993 }
1994 }
1995
1996 xmlFree(nsListDup);
1997 return(0);
1998}
1999#endif
2000
Daniel Veillardcfa0d812002-01-17 08:46:58 +00002001/**
Daniel Veillard1e208222002-10-22 14:25:25 +00002002 * xmlShellGrep:
2003 * @ctxt: the shell context
2004 * @arg: the string or regular expression to find
2005 * @node: a node
2006 * @node2: unused
2007 *
2008 * Implements the XML shell function "grep"
2009 * dumps informations about the node (namespace, attributes, content).
2010 *
2011 * Returns 0
2012 */
Daniel Veillarde645e8c2002-10-22 17:35:37 +00002013static int
Daniel Veillard1e208222002-10-22 14:25:25 +00002014xmlShellGrep(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
2015 char *arg, xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2016{
2017 if (!ctxt)
2018 return (0);
2019 if (node == NULL)
2020 return (0);
2021 if (arg == NULL)
2022 return (0);
2023#ifdef LIBXML_REGEXP_ENABLED
2024 if ((xmlStrchr((xmlChar *) arg, '?')) ||
2025 (xmlStrchr((xmlChar *) arg, '*')) ||
2026 (xmlStrchr((xmlChar *) arg, '.')) ||
2027 (xmlStrchr((xmlChar *) arg, '['))) {
2028 }
2029#endif
2030 while (node != NULL) {
2031 if (node->type == XML_COMMENT_NODE) {
Daniel Veillarde645e8c2002-10-22 17:35:37 +00002032 if (xmlStrstr(node->content, (xmlChar *) arg)) {
Daniel Veillard1e208222002-10-22 14:25:25 +00002033
2034 fprintf(ctxt->output, "%s : ", xmlGetNodePath(node));
2035 xmlShellList(ctxt, NULL, node, NULL);
2036 }
2037 } else if (node->type == XML_TEXT_NODE) {
Daniel Veillarde645e8c2002-10-22 17:35:37 +00002038 if (xmlStrstr(node->content, (xmlChar *) arg)) {
Daniel Veillard1e208222002-10-22 14:25:25 +00002039
2040 fprintf(ctxt->output, "%s : ", xmlGetNodePath(node->parent));
Daniel Veillarde645e8c2002-10-22 17:35:37 +00002041 xmlShellList(ctxt, NULL, node->parent, NULL);
Daniel Veillard1e208222002-10-22 14:25:25 +00002042 }
2043 }
2044
2045 /*
2046 * Browse the full subtree, deep first
2047 */
2048
2049 if ((node->type == XML_DOCUMENT_NODE) ||
2050 (node->type == XML_HTML_DOCUMENT_NODE)) {
2051 node = ((xmlDocPtr) node)->children;
2052 } else if ((node->children != NULL)
2053 && (node->type != XML_ENTITY_REF_NODE)) {
2054 /* deep first */
2055 node = node->children;
2056 } else if (node->next != NULL) {
2057 /* then siblings */
2058 node = node->next;
2059 } else {
2060 /* go up to parents->next if needed */
2061 while (node != NULL) {
2062 if (node->parent != NULL) {
2063 node = node->parent;
2064 }
2065 if (node->next != NULL) {
2066 node = node->next;
2067 break;
2068 }
2069 if (node->parent == NULL) {
2070 node = NULL;
2071 break;
2072 }
2073 }
2074 }
2075 }
2076 return (0);
2077}
2078
2079/**
Owen Taylor3473f882001-02-23 17:55:21 +00002080 * xmlShellDir:
2081 * @ctxt: the shell context
2082 * @arg: unused
2083 * @node: a node
2084 * @node2: unused
2085 *
2086 * Implements the XML shell function "dir"
2087 * dumps informations about the node (namespace, attributes, content).
2088 *
2089 * Returns 0
2090 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002091int
2092xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
2093 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
2094 xmlNodePtr node2 ATTRIBUTE_UNUSED)
2095{
Daniel Veillard321be0c2002-10-08 21:26:42 +00002096 if (!ctxt)
2097 return (0);
Daniel Veillard5e926fa2002-01-22 21:44:25 +00002098 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002099 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00002100 return (0);
2101 }
Owen Taylor3473f882001-02-23 17:55:21 +00002102 if ((node->type == XML_DOCUMENT_NODE) ||
2103 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002104 xmlDebugDumpDocumentHead(ctxt->output, (xmlDocPtr) node);
Owen Taylor3473f882001-02-23 17:55:21 +00002105 } else if (node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002106 xmlDebugDumpAttr(ctxt->output, (xmlAttrPtr) node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00002107 } else {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002108 xmlDebugDumpOneNode(ctxt->output, node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00002109 }
Daniel Veillard78d12092001-10-11 09:12:24 +00002110 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002111}
2112
Daniel Veillard29b17482004-08-16 00:39:03 +00002113/**
2114 * xmlShellSetContent:
2115 * @ctxt: the shell context
2116 * @value: the content as a string
2117 * @node: a node
2118 * @node2: unused
2119 *
2120 * Implements the XML shell function "dir"
2121 * dumps informations about the node (namespace, attributes, content).
2122 *
2123 * Returns 0
2124 */
2125static int
2126xmlShellSetContent(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
2127 char *value, xmlNodePtr node,
2128 xmlNodePtr node2 ATTRIBUTE_UNUSED)
2129{
2130 xmlNodePtr results;
2131 xmlParserErrors ret;
2132
2133 if (!ctxt)
2134 return (0);
2135 if (node == NULL) {
2136 fprintf(ctxt->output, "NULL\n");
2137 return (0);
2138 }
2139 if (value == NULL) {
2140 fprintf(ctxt->output, "NULL\n");
2141 return (0);
2142 }
2143
2144 ret = xmlParseInNodeContext(node, value, strlen(value), 0, &results);
2145 if (ret == XML_ERR_OK) {
2146 if (node->children != NULL) {
2147 xmlFreeNodeList(node->children);
2148 node->children = NULL;
2149 node->last = NULL;
2150 }
2151 xmlAddChildList(node, results);
2152 } else {
2153 fprintf(ctxt->output, "failed to parse content\n");
2154 }
2155 return (0);
2156}
2157
Daniel Veillard522bc602004-02-21 11:53:09 +00002158#ifdef LIBXML_SCHEMAS_ENABLED
2159/**
2160 * xmlShellRNGValidate:
2161 * @ctxt: the shell context
2162 * @schemas: the path to the Relax-NG schemas
2163 * @node: a node
2164 * @node2: unused
2165 *
2166 * Implements the XML shell function "relaxng"
2167 * validating the instance against a Relax-NG schemas
2168 *
2169 * Returns 0
2170 */
2171static int
2172xmlShellRNGValidate(xmlShellCtxtPtr sctxt, char *schemas,
2173 xmlNodePtr node ATTRIBUTE_UNUSED,
2174 xmlNodePtr node2 ATTRIBUTE_UNUSED)
2175{
2176 xmlRelaxNGPtr relaxngschemas;
2177 xmlRelaxNGParserCtxtPtr ctxt;
2178 xmlRelaxNGValidCtxtPtr vctxt;
2179 int ret;
2180
2181 ctxt = xmlRelaxNGNewParserCtxt(schemas);
2182 xmlRelaxNGSetParserErrors(ctxt,
2183 (xmlRelaxNGValidityErrorFunc) fprintf,
2184 (xmlRelaxNGValidityWarningFunc) fprintf,
2185 stderr);
2186 relaxngschemas = xmlRelaxNGParse(ctxt);
2187 xmlRelaxNGFreeParserCtxt(ctxt);
2188 if (relaxngschemas == NULL) {
2189 xmlGenericError(xmlGenericErrorContext,
2190 "Relax-NG schema %s failed to compile\n", schemas);
2191 return(-1);
2192 }
2193 vctxt = xmlRelaxNGNewValidCtxt(relaxngschemas);
2194 xmlRelaxNGSetValidErrors(vctxt,
2195 (xmlRelaxNGValidityErrorFunc) fprintf,
2196 (xmlRelaxNGValidityWarningFunc) fprintf,
2197 stderr);
2198 ret = xmlRelaxNGValidateDoc(vctxt, sctxt->doc);
2199 if (ret == 0) {
2200 fprintf(stderr, "%s validates\n", sctxt->filename);
2201 } else if (ret > 0) {
2202 fprintf(stderr, "%s fails to validate\n", sctxt->filename);
2203 } else {
2204 fprintf(stderr, "%s validation generated an internal error\n",
2205 sctxt->filename);
2206 }
2207 xmlRelaxNGFreeValidCtxt(vctxt);
2208 if (relaxngschemas != NULL)
2209 xmlRelaxNGFree(relaxngschemas);
2210 return(0);
2211}
2212#endif
2213
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002214#ifdef LIBXML_OUTPUT_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00002215/**
2216 * xmlShellCat:
2217 * @ctxt: the shell context
2218 * @arg: unused
2219 * @node: a node
2220 * @node2: unused
2221 *
2222 * Implements the XML shell function "cat"
2223 * dumps the serialization node content (XML or HTML).
2224 *
2225 * Returns 0
2226 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002227int
2228xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
2229 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2230{
Daniel Veillard321be0c2002-10-08 21:26:42 +00002231 if (!ctxt)
2232 return (0);
Daniel Veillard5e926fa2002-01-22 21:44:25 +00002233 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002234 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00002235 return (0);
2236 }
Owen Taylor3473f882001-02-23 17:55:21 +00002237 if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
2238#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002239 if (node->type == XML_HTML_DOCUMENT_NODE)
Daniel Veillard321be0c2002-10-08 21:26:42 +00002240 htmlDocDump(ctxt->output, (htmlDocPtr) node);
Daniel Veillard78d12092001-10-11 09:12:24 +00002241 else
Daniel Veillard321be0c2002-10-08 21:26:42 +00002242 htmlNodeDumpFile(ctxt->output, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00002243#else
Daniel Veillard78d12092001-10-11 09:12:24 +00002244 if (node->type == XML_DOCUMENT_NODE)
Daniel Veillard321be0c2002-10-08 21:26:42 +00002245 xmlDocDump(ctxt->output, (xmlDocPtr) node);
Daniel Veillard78d12092001-10-11 09:12:24 +00002246 else
Daniel Veillard321be0c2002-10-08 21:26:42 +00002247 xmlElemDump(ctxt->output, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00002248#endif /* LIBXML_HTML_ENABLED */
2249 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00002250 if (node->type == XML_DOCUMENT_NODE)
Daniel Veillard321be0c2002-10-08 21:26:42 +00002251 xmlDocDump(ctxt->output, (xmlDocPtr) node);
Daniel Veillard78d12092001-10-11 09:12:24 +00002252 else
Daniel Veillard321be0c2002-10-08 21:26:42 +00002253 xmlElemDump(ctxt->output, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00002254 }
Daniel Veillard321be0c2002-10-08 21:26:42 +00002255 fprintf(ctxt->output, "\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00002256 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002257}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002258#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00002259
2260/**
2261 * xmlShellLoad:
2262 * @ctxt: the shell context
2263 * @filename: the file name
2264 * @node: unused
2265 * @node2: unused
2266 *
2267 * Implements the XML shell function "load"
2268 * loads a new document specified by the filename
2269 *
2270 * Returns 0 or -1 if loading failed
2271 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002272int
2273xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename,
2274 xmlNodePtr node ATTRIBUTE_UNUSED,
2275 xmlNodePtr node2 ATTRIBUTE_UNUSED)
2276{
Owen Taylor3473f882001-02-23 17:55:21 +00002277 xmlDocPtr doc;
2278 int html = 0;
2279
2280 if (ctxt->doc != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002281 html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
Owen Taylor3473f882001-02-23 17:55:21 +00002282
2283 if (html) {
2284#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002285 doc = htmlParseFile(filename, NULL);
2286#else
Daniel Veillard321be0c2002-10-08 21:26:42 +00002287 fprintf(ctxt->output, "HTML support not compiled in\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00002288 doc = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00002289#endif /* LIBXML_HTML_ENABLED */
2290 } else {
Daniel Veillardebe25d42004-03-25 09:35:49 +00002291 doc = xmlReadFile(filename,NULL,0);
Owen Taylor3473f882001-02-23 17:55:21 +00002292 }
2293 if (doc != NULL) {
2294 if (ctxt->loaded == 1) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002295 xmlFreeDoc(ctxt->doc);
2296 }
2297 ctxt->loaded = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00002298#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002299 xmlXPathFreeContext(ctxt->pctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00002300#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00002301 xmlFree(ctxt->filename);
2302 ctxt->doc = doc;
2303 ctxt->node = (xmlNodePtr) doc;
Owen Taylor3473f882001-02-23 17:55:21 +00002304#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002305 ctxt->pctxt = xmlXPathNewContext(doc);
Owen Taylor3473f882001-02-23 17:55:21 +00002306#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard85095e22003-04-23 13:56:44 +00002307 ctxt->filename = (char *) xmlCanonicPath((xmlChar *) filename);
Owen Taylor3473f882001-02-23 17:55:21 +00002308 } else
Daniel Veillard78d12092001-10-11 09:12:24 +00002309 return (-1);
2310 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002311}
2312
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002313#ifdef LIBXML_OUTPUT_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00002314/**
2315 * xmlShellWrite:
2316 * @ctxt: the shell context
2317 * @filename: the file name
2318 * @node: a node in the tree
2319 * @node2: unused
2320 *
2321 * Implements the XML shell function "write"
Daniel Veillardcbaf3992001-12-31 16:16:02 +00002322 * Write the current node to the filename, it saves the serialization
Owen Taylor3473f882001-02-23 17:55:21 +00002323 * of the subtree under the @node specified
2324 *
2325 * Returns 0 or -1 in case of error
2326 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002327int
Owen Taylor3473f882001-02-23 17:55:21 +00002328xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
Daniel Veillard78d12092001-10-11 09:12:24 +00002329 xmlNodePtr node2 ATTRIBUTE_UNUSED)
2330{
Owen Taylor3473f882001-02-23 17:55:21 +00002331 if (node == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002332 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002333 if ((filename == NULL) || (filename[0] == 0)) {
2334 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00002335 "Write command requires a filename argument\n");
2336 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002337 }
2338#ifdef W_OK
2339 if (access((char *) filename, W_OK)) {
2340 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00002341 "Cannot write to %s\n", filename);
2342 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002343 }
Daniel Veillard78d12092001-10-11 09:12:24 +00002344#endif
2345 switch (node->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00002346 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00002347 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
2348 xmlGenericError(xmlGenericErrorContext,
2349 "Failed to write to %s\n", filename);
2350 return (-1);
2351 }
2352 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002353 case XML_HTML_DOCUMENT_NODE:
2354#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002355 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
2356 xmlGenericError(xmlGenericErrorContext,
2357 "Failed to write to %s\n", filename);
2358 return (-1);
2359 }
Owen Taylor3473f882001-02-23 17:55:21 +00002360#else
Daniel Veillard78d12092001-10-11 09:12:24 +00002361 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
2362 xmlGenericError(xmlGenericErrorContext,
2363 "Failed to write to %s\n", filename);
2364 return (-1);
2365 }
Owen Taylor3473f882001-02-23 17:55:21 +00002366#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00002367 break;
2368 default:{
2369 FILE *f;
Owen Taylor3473f882001-02-23 17:55:21 +00002370
Daniel Veillard78d12092001-10-11 09:12:24 +00002371 f = fopen((char *) filename, "w");
2372 if (f == NULL) {
2373 xmlGenericError(xmlGenericErrorContext,
2374 "Failed to write to %s\n", filename);
2375 return (-1);
2376 }
2377 xmlElemDump(f, ctxt->doc, node);
2378 fclose(f);
2379 }
Owen Taylor3473f882001-02-23 17:55:21 +00002380 }
Daniel Veillard78d12092001-10-11 09:12:24 +00002381 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002382}
2383
2384/**
2385 * xmlShellSave:
2386 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00002387 * @filename: the file name (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00002388 * @node: unused
2389 * @node2: unused
2390 *
2391 * Implements the XML shell function "save"
2392 * Write the current document to the filename, or it's original name
2393 *
2394 * Returns 0 or -1 in case of error
2395 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002396int
2397xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
2398 xmlNodePtr node ATTRIBUTE_UNUSED,
2399 xmlNodePtr node2 ATTRIBUTE_UNUSED)
2400{
Owen Taylor3473f882001-02-23 17:55:21 +00002401 if (ctxt->doc == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002402 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002403 if ((filename == NULL) || (filename[0] == 0))
2404 filename = ctxt->filename;
2405#ifdef W_OK
2406 if (access((char *) filename, W_OK)) {
2407 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00002408 "Cannot save to %s\n", filename);
2409 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002410 }
2411#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00002412 switch (ctxt->doc->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00002413 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00002414 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
2415 xmlGenericError(xmlGenericErrorContext,
2416 "Failed to save to %s\n", filename);
2417 }
2418 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002419 case XML_HTML_DOCUMENT_NODE:
2420#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002421 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
2422 xmlGenericError(xmlGenericErrorContext,
2423 "Failed to save to %s\n", filename);
2424 }
Owen Taylor3473f882001-02-23 17:55:21 +00002425#else
Daniel Veillard78d12092001-10-11 09:12:24 +00002426 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
2427 xmlGenericError(xmlGenericErrorContext,
2428 "Failed to save to %s\n", filename);
2429 }
Owen Taylor3473f882001-02-23 17:55:21 +00002430#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00002431 break;
2432 default:
2433 xmlGenericError(xmlGenericErrorContext,
2434 "To save to subparts of a document use the 'write' command\n");
2435 return (-1);
2436
Owen Taylor3473f882001-02-23 17:55:21 +00002437 }
Daniel Veillard78d12092001-10-11 09:12:24 +00002438 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002439}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002440#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00002441
Daniel Veillardf54cd532004-02-25 11:52:31 +00002442#ifdef LIBXML_VALID_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00002443/**
2444 * xmlShellValidate:
2445 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00002446 * @dtd: the DTD URI (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00002447 * @node: unused
2448 * @node2: unused
2449 *
2450 * Implements the XML shell function "validate"
2451 * Validate the document, if a DTD path is provided, then the validation
2452 * is done against the given DTD.
2453 *
2454 * Returns 0 or -1 in case of error
2455 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002456int
2457xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd,
2458 xmlNodePtr node ATTRIBUTE_UNUSED,
2459 xmlNodePtr node2 ATTRIBUTE_UNUSED)
2460{
Owen Taylor3473f882001-02-23 17:55:21 +00002461 xmlValidCtxt vctxt;
2462 int res = -1;
2463
2464 vctxt.userData = stderr;
2465 vctxt.error = (xmlValidityErrorFunc) fprintf;
2466 vctxt.warning = (xmlValidityWarningFunc) fprintf;
2467
2468 if ((dtd == NULL) || (dtd[0] == 0)) {
2469 res = xmlValidateDocument(&vctxt, ctxt->doc);
2470 } else {
2471 xmlDtdPtr subset;
2472
Daniel Veillard78d12092001-10-11 09:12:24 +00002473 subset = xmlParseDTD(NULL, (xmlChar *) dtd);
2474 if (subset != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00002475 res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
2476
Daniel Veillard78d12092001-10-11 09:12:24 +00002477 xmlFreeDtd(subset);
2478 }
Owen Taylor3473f882001-02-23 17:55:21 +00002479 }
Daniel Veillard78d12092001-10-11 09:12:24 +00002480 return (res);
Owen Taylor3473f882001-02-23 17:55:21 +00002481}
Daniel Veillardf54cd532004-02-25 11:52:31 +00002482#endif /* LIBXML_VALID_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00002483
2484/**
2485 * xmlShellDu:
2486 * @ctxt: the shell context
2487 * @arg: unused
2488 * @tree: a node defining a subtree
2489 * @node2: unused
2490 *
2491 * Implements the XML shell function "du"
2492 * show the structure of the subtree under node @tree
2493 * If @tree is null, the command works on the current node.
2494 *
2495 * Returns 0 or -1 in case of error
2496 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002497int
Daniel Veillard321be0c2002-10-08 21:26:42 +00002498xmlShellDu(xmlShellCtxtPtr ctxt,
Daniel Veillard78d12092001-10-11 09:12:24 +00002499 char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree,
2500 xmlNodePtr node2 ATTRIBUTE_UNUSED)
2501{
Owen Taylor3473f882001-02-23 17:55:21 +00002502 xmlNodePtr node;
Daniel Veillard78d12092001-10-11 09:12:24 +00002503 int indent = 0, i;
Owen Taylor3473f882001-02-23 17:55:21 +00002504
Daniel Veillard321be0c2002-10-08 21:26:42 +00002505 if (!ctxt)
2506 return (-1);
2507
Daniel Veillard78d12092001-10-11 09:12:24 +00002508 if (tree == NULL)
2509 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002510 node = tree;
2511 while (node != NULL) {
2512 if ((node->type == XML_DOCUMENT_NODE) ||
2513 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002514 fprintf(ctxt->output, "/\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00002515 } else if (node->type == XML_ELEMENT_NODE) {
2516 for (i = 0; i < indent; i++)
Daniel Veillard321be0c2002-10-08 21:26:42 +00002517 fprintf(ctxt->output, " ");
2518 fprintf(ctxt->output, "%s\n", node->name);
Daniel Veillard78d12092001-10-11 09:12:24 +00002519 } else {
2520 }
Owen Taylor3473f882001-02-23 17:55:21 +00002521
Daniel Veillard78d12092001-10-11 09:12:24 +00002522 /*
2523 * Browse the full subtree, deep first
2524 */
Owen Taylor3473f882001-02-23 17:55:21 +00002525
2526 if ((node->type == XML_DOCUMENT_NODE) ||
2527 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002528 node = ((xmlDocPtr) node)->children;
2529 } else if ((node->children != NULL)
2530 && (node->type != XML_ENTITY_REF_NODE)) {
2531 /* deep first */
2532 node = node->children;
2533 indent++;
2534 } else if ((node != tree) && (node->next != NULL)) {
2535 /* then siblings */
2536 node = node->next;
2537 } else if (node != tree) {
2538 /* go up to parents->next if needed */
2539 while (node != tree) {
2540 if (node->parent != NULL) {
2541 node = node->parent;
2542 indent--;
2543 }
2544 if ((node != tree) && (node->next != NULL)) {
2545 node = node->next;
2546 break;
2547 }
2548 if (node->parent == NULL) {
2549 node = NULL;
2550 break;
2551 }
2552 if (node == tree) {
2553 node = NULL;
2554 break;
2555 }
2556 }
2557 /* exit condition */
2558 if (node == tree)
2559 node = NULL;
2560 } else
2561 node = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00002562 }
Daniel Veillard78d12092001-10-11 09:12:24 +00002563 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002564}
2565
2566/**
2567 * xmlShellPwd:
2568 * @ctxt: the shell context
2569 * @buffer: the output buffer
Daniel Veillard9d06d302002-01-22 18:15:52 +00002570 * @node: a node
Owen Taylor3473f882001-02-23 17:55:21 +00002571 * @node2: unused
2572 *
2573 * Implements the XML shell function "pwd"
2574 * Show the full path from the root to the node, if needed building
2575 * thumblers when similar elements exists at a given ancestor level.
2576 * The output is compatible with XPath commands.
2577 *
2578 * Returns 0 or -1 in case of error
2579 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002580int
2581xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
2582 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2583{
Daniel Veillardc6e013a2001-11-10 10:08:57 +00002584 xmlChar *path;
Owen Taylor3473f882001-02-23 17:55:21 +00002585
Daniel Veillard78d12092001-10-11 09:12:24 +00002586 if (node == NULL)
2587 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002588
Daniel Veillardc6e013a2001-11-10 10:08:57 +00002589 path = xmlGetNodePath(node);
2590 if (path == NULL)
2591 return (-1);
2592
2593 /*
2594 * This test prevents buffer overflow, because this routine
2595 * is only called by xmlShell, in which the second argument is
2596 * 500 chars long.
2597 * It is a dirty hack before a cleaner solution is found.
2598 * Documentation should mention that the second argument must
2599 * be at least 500 chars long, and could be stripped if too long.
2600 */
2601 snprintf(buffer, 499, "%s", path);
2602 buffer[499] = '0';
2603 xmlFree(path);
2604
Daniel Veillard78d12092001-10-11 09:12:24 +00002605 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002606}
2607
2608/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002609 * xmlShell:
Owen Taylor3473f882001-02-23 17:55:21 +00002610 * @doc: the initial document
2611 * @filename: the output buffer
2612 * @input: the line reading function
Daniel Veillard321be0c2002-10-08 21:26:42 +00002613 * @output: the output FILE*, defaults to stdout if NULL
Owen Taylor3473f882001-02-23 17:55:21 +00002614 *
2615 * Implements the XML shell
2616 * This allow to load, validate, view, modify and save a document
2617 * using a environment similar to a UNIX commandline.
2618 */
2619void
2620xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
Daniel Veillard78d12092001-10-11 09:12:24 +00002621 FILE * output)
2622{
Owen Taylor3473f882001-02-23 17:55:21 +00002623 char prompt[500] = "/ > ";
2624 char *cmdline = NULL, *cur;
2625 int nbargs;
2626 char command[100];
2627 char arg[400];
2628 int i;
2629 xmlShellCtxtPtr ctxt;
2630 xmlXPathObjectPtr list;
2631
2632 if (doc == NULL)
2633 return;
2634 if (filename == NULL)
2635 return;
2636 if (input == NULL)
2637 return;
2638 if (output == NULL)
Daniel Veillard321be0c2002-10-08 21:26:42 +00002639 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +00002640 ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
Daniel Veillard78d12092001-10-11 09:12:24 +00002641 if (ctxt == NULL)
Owen Taylor3473f882001-02-23 17:55:21 +00002642 return;
2643 ctxt->loaded = 0;
2644 ctxt->doc = doc;
2645 ctxt->input = input;
2646 ctxt->output = output;
2647 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
Daniel Veillard78d12092001-10-11 09:12:24 +00002648 ctxt->node = (xmlNodePtr) ctxt->doc;
Owen Taylor3473f882001-02-23 17:55:21 +00002649
2650#ifdef LIBXML_XPATH_ENABLED
2651 ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
2652 if (ctxt->pctxt == NULL) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002653 xmlFree(ctxt);
2654 return;
Owen Taylor3473f882001-02-23 17:55:21 +00002655 }
2656#endif /* LIBXML_XPATH_ENABLED */
2657 while (1) {
2658 if (ctxt->node == (xmlNodePtr) ctxt->doc)
Aleksey Sanin49cc9752002-06-14 17:07:10 +00002659 snprintf(prompt, sizeof(prompt), "%s > ", "/");
Daniel Veillard7a985a12003-07-06 17:57:42 +00002660 else if ((ctxt->node != NULL) && (ctxt->node->name))
Daniel Veillard78d12092001-10-11 09:12:24 +00002661 snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00002662 else
Aleksey Sanin49cc9752002-06-14 17:07:10 +00002663 snprintf(prompt, sizeof(prompt), "? > ");
Owen Taylor3473f882001-02-23 17:55:21 +00002664 prompt[sizeof(prompt) - 1] = 0;
2665
Daniel Veillard78d12092001-10-11 09:12:24 +00002666 /*
2667 * Get a new command line
2668 */
Owen Taylor3473f882001-02-23 17:55:21 +00002669 cmdline = ctxt->input(prompt);
Daniel Veillard78d12092001-10-11 09:12:24 +00002670 if (cmdline == NULL)
2671 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002672
Daniel Veillard78d12092001-10-11 09:12:24 +00002673 /*
2674 * Parse the command itself
2675 */
2676 cur = cmdline;
2677 nbargs = 0;
2678 while ((*cur == ' ') || (*cur == '\t'))
2679 cur++;
2680 i = 0;
2681 while ((*cur != ' ') && (*cur != '\t') &&
2682 (*cur != '\n') && (*cur != '\r')) {
2683 if (*cur == 0)
2684 break;
2685 command[i++] = *cur++;
2686 }
2687 command[i] = 0;
2688 if (i == 0)
2689 continue;
2690 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00002691
Daniel Veillard78d12092001-10-11 09:12:24 +00002692 /*
2693 * Parse the argument
2694 */
2695 while ((*cur == ' ') || (*cur == '\t'))
2696 cur++;
2697 i = 0;
2698 while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
2699 if (*cur == 0)
2700 break;
2701 arg[i++] = *cur++;
2702 }
2703 arg[i] = 0;
2704 if (i != 0)
2705 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00002706
Daniel Veillard78d12092001-10-11 09:12:24 +00002707 /*
2708 * start interpreting the command
2709 */
Owen Taylor3473f882001-02-23 17:55:21 +00002710 if (!strcmp(command, "exit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002711 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002712 if (!strcmp(command, "quit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002713 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002714 if (!strcmp(command, "bye"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002715 break;
Daniel Veillard5004f422001-11-08 13:53:05 +00002716 if (!strcmp(command, "help")) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002717 fprintf(ctxt->output, "\tbase display XML base of the node\n");
2718 fprintf(ctxt->output, "\tsetbase URI change the XML base of the node\n");
2719 fprintf(ctxt->output, "\tbye leave shell\n");
2720 fprintf(ctxt->output, "\tcat [node] display node or current node\n");
2721 fprintf(ctxt->output, "\tcd [path] change directory to path or to root\n");
2722 fprintf(ctxt->output, "\tdir [path] dumps informations about the node (namespace, attributes, content)\n");
2723 fprintf(ctxt->output, "\tdu [path] show the structure of the subtree under path or the current node\n");
2724 fprintf(ctxt->output, "\texit leave shell\n");
2725 fprintf(ctxt->output, "\thelp display this help\n");
2726 fprintf(ctxt->output, "\tfree display memory usage\n");
2727 fprintf(ctxt->output, "\tload [name] load a new document with name\n");
2728 fprintf(ctxt->output, "\tls [path] list contents of path or the current directory\n");
Daniel Veillardc14c3892004-08-16 12:34:50 +00002729 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 +00002730#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard321be0c2002-10-08 21:26:42 +00002731 fprintf(ctxt->output, "\txpath expr evaluate the XPath expression in that context and print the result\n");
Daniel Veillardbbaa9972004-06-16 14:08:33 +00002732 fprintf(ctxt->output, "\tsetns nsreg register a namespace to a prefix in the XPath evaluation context\n");
2733 fprintf(ctxt->output, "\t format for nsreg is: prefix=[nsuri] (i.e. prefix= unsets a prefix)\n");
Daniel Veillard2070c482002-01-22 22:12:19 +00002734#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard321be0c2002-10-08 21:26:42 +00002735 fprintf(ctxt->output, "\tpwd display current working directory\n");
2736 fprintf(ctxt->output, "\tquit leave shell\n");
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002737#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard321be0c2002-10-08 21:26:42 +00002738 fprintf(ctxt->output, "\tsave [name] save this document to name or the original name\n");
Daniel Veillard321be0c2002-10-08 21:26:42 +00002739 fprintf(ctxt->output, "\twrite [name] write the current node to the filename\n");
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002740#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillardf54cd532004-02-25 11:52:31 +00002741#ifdef LIBXML_VALID_ENABLED
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002742 fprintf(ctxt->output, "\tvalidate check the document for errors\n");
Daniel Veillardf54cd532004-02-25 11:52:31 +00002743#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard522bc602004-02-21 11:53:09 +00002744#ifdef LIBXML_SCHEMAS_ENABLED
2745 fprintf(ctxt->output, "\trelaxng rng validate the document agaisnt the Relax-NG schemas\n");
2746#endif
Daniel Veillard1e208222002-10-22 14:25:25 +00002747 fprintf(ctxt->output, "\tgrep string search for a string in the subtree\n");
Daniel Veillardf54cd532004-02-25 11:52:31 +00002748#ifdef LIBXML_VALID_ENABLED
Daniel Veillard5004f422001-11-08 13:53:05 +00002749 } else if (!strcmp(command, "validate")) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002750 xmlShellValidate(ctxt, arg, NULL, NULL);
Daniel Veillardf54cd532004-02-25 11:52:31 +00002751#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00002752 } else if (!strcmp(command, "load")) {
2753 xmlShellLoad(ctxt, arg, NULL, NULL);
Daniel Veillard522bc602004-02-21 11:53:09 +00002754#ifdef LIBXML_SCHEMAS_ENABLED
2755 } else if (!strcmp(command, "relaxng")) {
2756 xmlShellRNGValidate(ctxt, arg, NULL, NULL);
2757#endif
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002758#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002759 } else if (!strcmp(command, "save")) {
2760 xmlShellSave(ctxt, arg, NULL, NULL);
2761 } else if (!strcmp(command, "write")) {
2762 xmlShellWrite(ctxt, arg, NULL, NULL);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002763#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard1e208222002-10-22 14:25:25 +00002764 } else if (!strcmp(command, "grep")) {
2765 xmlShellGrep(ctxt, arg, ctxt->node, NULL);
Daniel Veillard78d12092001-10-11 09:12:24 +00002766 } else if (!strcmp(command, "free")) {
2767 if (arg[0] == 0) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002768 xmlMemShow(ctxt->output, 0);
Daniel Veillard78d12092001-10-11 09:12:24 +00002769 } else {
2770 int len = 0;
Owen Taylor3473f882001-02-23 17:55:21 +00002771
Daniel Veillard78d12092001-10-11 09:12:24 +00002772 sscanf(arg, "%d", &len);
Daniel Veillard321be0c2002-10-08 21:26:42 +00002773 xmlMemShow(ctxt->output, len);
Daniel Veillard78d12092001-10-11 09:12:24 +00002774 }
2775 } else if (!strcmp(command, "pwd")) {
2776 char dir[500];
Owen Taylor3473f882001-02-23 17:55:21 +00002777
Daniel Veillard78d12092001-10-11 09:12:24 +00002778 if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
Daniel Veillard321be0c2002-10-08 21:26:42 +00002779 fprintf(ctxt->output, "%s\n", dir);
Daniel Veillard78d12092001-10-11 09:12:24 +00002780 } else if (!strcmp(command, "du")) {
2781 xmlShellDu(ctxt, NULL, ctxt->node, NULL);
2782 } else if (!strcmp(command, "base")) {
2783 xmlShellBase(ctxt, NULL, ctxt->node, NULL);
Daniel Veillard29b17482004-08-16 00:39:03 +00002784 } else if (!strcmp(command, "set")) {
2785 xmlShellSetContent(ctxt, arg, ctxt->node, NULL);
Daniel Veillard2070c482002-01-22 22:12:19 +00002786#ifdef LIBXML_XPATH_ENABLED
Daniel Veillardbbaa9972004-06-16 14:08:33 +00002787 } else if (!strcmp(command, "setns")) {
2788 if (arg[0] == 0) {
2789 xmlGenericError(xmlGenericErrorContext,
2790 "setns: prefix=[nsuri] required\n");
2791 } else {
2792 xmlShellRegisterNamespace(ctxt, arg, NULL, NULL);
2793 }
Daniel Veillard2070c482002-01-22 22:12:19 +00002794 } else if (!strcmp(command, "xpath")) {
2795 if (arg[0] == 0) {
2796 xmlGenericError(xmlGenericErrorContext,
2797 "xpath: expression required\n");
2798 } else {
2799 ctxt->pctxt->node = ctxt->node;
2800 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
Daniel Veillard321be0c2002-10-08 21:26:42 +00002801 xmlXPathDebugDumpObject(ctxt->output, list, 0);
Daniel Veillard2070c482002-01-22 22:12:19 +00002802 xmlXPathFreeObject(list);
2803 }
2804#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard2156d432004-03-04 15:59:36 +00002805#ifdef LIBXML_TREE_ENABLED
Daniel Veillardcfa0d812002-01-17 08:46:58 +00002806 } else if (!strcmp(command, "setbase")) {
2807 xmlShellSetBase(ctxt, arg, ctxt->node, NULL);
Daniel Veillard2156d432004-03-04 15:59:36 +00002808#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00002809 } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) {
2810 int dir = (!strcmp(command, "dir"));
2811
2812 if (arg[0] == 0) {
2813 if (dir)
2814 xmlShellDir(ctxt, NULL, ctxt->node, NULL);
2815 else
2816 xmlShellList(ctxt, NULL, ctxt->node, NULL);
2817 } else {
2818 ctxt->pctxt->node = ctxt->node;
Daniel Veillard61d80a22001-04-27 17:13:01 +00002819#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002820 ctxt->pctxt->node = ctxt->node;
2821 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2822#else
2823 list = NULL;
2824#endif /* LIBXML_XPATH_ENABLED */
2825 if (list != NULL) {
2826 switch (list->type) {
2827 case XPATH_UNDEFINED:
2828 xmlGenericError(xmlGenericErrorContext,
2829 "%s: no such node\n", arg);
2830 break;
2831 case XPATH_NODESET:{
2832 int indx;
2833
Daniel Veillarda6825e82001-11-07 13:33:59 +00002834 if (list->nodesetval == NULL)
2835 break;
2836
Daniel Veillard78d12092001-10-11 09:12:24 +00002837 for (indx = 0;
2838 indx < list->nodesetval->nodeNr;
2839 indx++) {
2840 if (dir)
2841 xmlShellDir(ctxt, NULL,
2842 list->nodesetval->
2843 nodeTab[indx], NULL);
2844 else
2845 xmlShellList(ctxt, NULL,
2846 list->nodesetval->
2847 nodeTab[indx], NULL);
2848 }
2849 break;
2850 }
2851 case XPATH_BOOLEAN:
2852 xmlGenericError(xmlGenericErrorContext,
2853 "%s is a Boolean\n", arg);
2854 break;
2855 case XPATH_NUMBER:
2856 xmlGenericError(xmlGenericErrorContext,
2857 "%s is a number\n", arg);
2858 break;
2859 case XPATH_STRING:
2860 xmlGenericError(xmlGenericErrorContext,
2861 "%s is a string\n", arg);
2862 break;
2863 case XPATH_POINT:
2864 xmlGenericError(xmlGenericErrorContext,
2865 "%s is a point\n", arg);
2866 break;
2867 case XPATH_RANGE:
2868 xmlGenericError(xmlGenericErrorContext,
2869 "%s is a range\n", arg);
2870 break;
2871 case XPATH_LOCATIONSET:
2872 xmlGenericError(xmlGenericErrorContext,
2873 "%s is a range\n", arg);
2874 break;
2875 case XPATH_USERS:
2876 xmlGenericError(xmlGenericErrorContext,
2877 "%s is user-defined\n", arg);
2878 break;
2879 case XPATH_XSLT_TREE:
2880 xmlGenericError(xmlGenericErrorContext,
2881 "%s is an XSLT value tree\n",
2882 arg);
2883 break;
2884 }
2885#ifdef LIBXML_XPATH_ENABLED
2886 xmlXPathFreeObject(list);
Daniel Veillard61d80a22001-04-27 17:13:01 +00002887#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00002888 } else {
2889 xmlGenericError(xmlGenericErrorContext,
2890 "%s: no such node\n", arg);
2891 }
2892 ctxt->pctxt->node = NULL;
2893 }
2894 } else if (!strcmp(command, "cd")) {
2895 if (arg[0] == 0) {
2896 ctxt->node = (xmlNodePtr) ctxt->doc;
2897 } else {
2898#ifdef LIBXML_XPATH_ENABLED
2899 ctxt->pctxt->node = ctxt->node;
2900 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2901#else
2902 list = NULL;
2903#endif /* LIBXML_XPATH_ENABLED */
2904 if (list != NULL) {
2905 switch (list->type) {
2906 case XPATH_UNDEFINED:
2907 xmlGenericError(xmlGenericErrorContext,
2908 "%s: no such node\n", arg);
2909 break;
2910 case XPATH_NODESET:
Daniel Veillarda6825e82001-11-07 13:33:59 +00002911 if (list->nodesetval != NULL) {
2912 if (list->nodesetval->nodeNr == 1) {
2913 ctxt->node = list->nodesetval->nodeTab[0];
Daniel Veillard7a985a12003-07-06 17:57:42 +00002914 if ((ctxt->node != NULL) &&
2915 (ctxt->node->type ==
2916 XML_NAMESPACE_DECL)) {
2917 xmlGenericError(xmlGenericErrorContext,
2918 "cannot cd to namespace\n");
2919 ctxt->node = NULL;
2920 }
Daniel Veillarda6825e82001-11-07 13:33:59 +00002921 } else
2922 xmlGenericError(xmlGenericErrorContext,
2923 "%s is a %d Node Set\n",
2924 arg,
2925 list->nodesetval->nodeNr);
Daniel Veillard78d12092001-10-11 09:12:24 +00002926 } else
2927 xmlGenericError(xmlGenericErrorContext,
Daniel Veillarda6825e82001-11-07 13:33:59 +00002928 "%s is an empty Node Set\n",
2929 arg);
Daniel Veillard78d12092001-10-11 09:12:24 +00002930 break;
2931 case XPATH_BOOLEAN:
2932 xmlGenericError(xmlGenericErrorContext,
2933 "%s is a Boolean\n", arg);
2934 break;
2935 case XPATH_NUMBER:
2936 xmlGenericError(xmlGenericErrorContext,
2937 "%s is a number\n", arg);
2938 break;
2939 case XPATH_STRING:
2940 xmlGenericError(xmlGenericErrorContext,
2941 "%s is a string\n", arg);
2942 break;
2943 case XPATH_POINT:
2944 xmlGenericError(xmlGenericErrorContext,
2945 "%s is a point\n", arg);
2946 break;
2947 case XPATH_RANGE:
2948 xmlGenericError(xmlGenericErrorContext,
2949 "%s is a range\n", arg);
2950 break;
2951 case XPATH_LOCATIONSET:
2952 xmlGenericError(xmlGenericErrorContext,
2953 "%s is a range\n", arg);
2954 break;
2955 case XPATH_USERS:
2956 xmlGenericError(xmlGenericErrorContext,
2957 "%s is user-defined\n", arg);
2958 break;
2959 case XPATH_XSLT_TREE:
2960 xmlGenericError(xmlGenericErrorContext,
2961 "%s is an XSLT value tree\n",
2962 arg);
2963 break;
2964 }
2965#ifdef LIBXML_XPATH_ENABLED
2966 xmlXPathFreeObject(list);
2967#endif
2968 } else {
2969 xmlGenericError(xmlGenericErrorContext,
2970 "%s: no such node\n", arg);
2971 }
2972 ctxt->pctxt->node = NULL;
2973 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002974#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002975 } else if (!strcmp(command, "cat")) {
2976 if (arg[0] == 0) {
2977 xmlShellCat(ctxt, NULL, ctxt->node, NULL);
2978 } else {
2979 ctxt->pctxt->node = ctxt->node;
2980#ifdef LIBXML_XPATH_ENABLED
2981 ctxt->pctxt->node = ctxt->node;
2982 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2983#else
2984 list = NULL;
2985#endif /* LIBXML_XPATH_ENABLED */
2986 if (list != NULL) {
2987 switch (list->type) {
2988 case XPATH_UNDEFINED:
2989 xmlGenericError(xmlGenericErrorContext,
2990 "%s: no such node\n", arg);
2991 break;
2992 case XPATH_NODESET:{
2993 int indx;
2994
Daniel Veillarda6825e82001-11-07 13:33:59 +00002995 if (list->nodesetval == NULL)
2996 break;
2997
Daniel Veillard78d12092001-10-11 09:12:24 +00002998 for (indx = 0;
2999 indx < list->nodesetval->nodeNr;
3000 indx++) {
3001 if (i > 0)
Daniel Veillard321be0c2002-10-08 21:26:42 +00003002 fprintf(ctxt->output, " -------\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00003003 xmlShellCat(ctxt, NULL,
3004 list->nodesetval->
3005 nodeTab[indx], NULL);
3006 }
3007 break;
3008 }
3009 case XPATH_BOOLEAN:
3010 xmlGenericError(xmlGenericErrorContext,
3011 "%s is a Boolean\n", arg);
3012 break;
3013 case XPATH_NUMBER:
3014 xmlGenericError(xmlGenericErrorContext,
3015 "%s is a number\n", arg);
3016 break;
3017 case XPATH_STRING:
3018 xmlGenericError(xmlGenericErrorContext,
3019 "%s is a string\n", arg);
3020 break;
3021 case XPATH_POINT:
3022 xmlGenericError(xmlGenericErrorContext,
3023 "%s is a point\n", arg);
3024 break;
3025 case XPATH_RANGE:
3026 xmlGenericError(xmlGenericErrorContext,
3027 "%s is a range\n", arg);
3028 break;
3029 case XPATH_LOCATIONSET:
3030 xmlGenericError(xmlGenericErrorContext,
3031 "%s is a range\n", arg);
3032 break;
3033 case XPATH_USERS:
3034 xmlGenericError(xmlGenericErrorContext,
3035 "%s is user-defined\n", arg);
3036 break;
3037 case XPATH_XSLT_TREE:
3038 xmlGenericError(xmlGenericErrorContext,
3039 "%s is an XSLT value tree\n",
3040 arg);
3041 break;
3042 }
3043#ifdef LIBXML_XPATH_ENABLED
3044 xmlXPathFreeObject(list);
3045#endif
3046 } else {
3047 xmlGenericError(xmlGenericErrorContext,
3048 "%s: no such node\n", arg);
3049 }
3050 ctxt->pctxt->node = NULL;
3051 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003052#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00003053 } else {
3054 xmlGenericError(xmlGenericErrorContext,
3055 "Unknown command %s\n", command);
3056 }
3057 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00003058 }
3059#ifdef LIBXML_XPATH_ENABLED
3060 xmlXPathFreeContext(ctxt->pctxt);
3061#endif /* LIBXML_XPATH_ENABLED */
3062 if (ctxt->loaded) {
3063 xmlFreeDoc(ctxt->doc);
3064 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00003065 if (ctxt->filename != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00003066 xmlFree(ctxt->filename);
Owen Taylor3473f882001-02-23 17:55:21 +00003067 xmlFree(ctxt);
3068 if (cmdline != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00003069 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00003070}
3071
3072#endif /* LIBXML_DEBUG_ENABLED */