blob: bb6560af2518d83fff31ea9c3fafcb3c26659b01 [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 Veillard5e2dace2001-07-18 19:30:27 +000037/**
38 * xmlDebugDumpString:
39 * @output: the FILE * for the output
40 * @str: the string
41 *
42 * Dumps informations about the string, shorten it if necessary
43 */
44void
45xmlDebugDumpString(FILE * output, const xmlChar * str)
46{
Owen Taylor3473f882001-02-23 17:55:21 +000047 int i;
Daniel Veillard5e2dace2001-07-18 19:30:27 +000048
Daniel Veillard7db38712002-02-07 16:39:11 +000049 if (output == NULL)
50 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +000051 if (str == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +000052 fprintf(output, "(NULL)");
53 return;
Owen Taylor3473f882001-02-23 17:55:21 +000054 }
Daniel Veillard5e2dace2001-07-18 19:30:27 +000055 for (i = 0; i < 40; i++)
56 if (str[i] == 0)
57 return;
William M. Brack76e95df2003-10-18 16:20:14 +000058 else if (IS_BLANK_CH(str[i]))
Daniel Veillard5e2dace2001-07-18 19:30:27 +000059 fputc(' ', output);
60 else if (str[i] >= 0x80)
61 fprintf(output, "#%X", str[i]);
62 else
63 fputc(str[i], output);
Owen Taylor3473f882001-02-23 17:55:21 +000064 fprintf(output, "...");
65}
66
Daniel Veillard56a4cb82001-03-24 17:00:36 +000067static void
68xmlDebugDumpDtdNode(FILE *output, xmlDtdPtr dtd, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +000069 int i;
70 char shift[100];
71
72 for (i = 0;((i < depth) && (i < 25));i++)
73 shift[2 * i] = shift[2 * i + 1] = ' ';
74 shift[2 * i] = shift[2 * i + 1] = 0;
75
76 fprintf(output, shift);
77
Daniel Veillard5e926fa2002-01-22 21:44:25 +000078 if (dtd == NULL) {
79 fprintf(output, "DTD node is NULL\n");
80 return;
81 }
82
Owen Taylor3473f882001-02-23 17:55:21 +000083 if (dtd->type != XML_DTD_NODE) {
84 fprintf(output, "PBM: not a DTD\n");
85 return;
86 }
87 if (dtd->name != NULL)
William M. Brack13dfa872004-09-18 04:52:08 +000088 fprintf(output, "DTD(%s)", (char *)dtd->name);
Owen Taylor3473f882001-02-23 17:55:21 +000089 else
90 fprintf(output, "DTD");
91 if (dtd->ExternalID != NULL)
William M. Brack13dfa872004-09-18 04:52:08 +000092 fprintf(output, ", PUBLIC %s", (char *)dtd->ExternalID);
Owen Taylor3473f882001-02-23 17:55:21 +000093 if (dtd->SystemID != NULL)
William M. Brack13dfa872004-09-18 04:52:08 +000094 fprintf(output, ", SYSTEM %s", (char *)dtd->SystemID);
Owen Taylor3473f882001-02-23 17:55:21 +000095 fprintf(output, "\n");
96 /*
97 * Do a bit of checking
98 */
99 if (dtd->parent == NULL)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000100 fprintf(output, "PBM: DTD has no parent\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000101 if (dtd->doc == NULL)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000102 fprintf(output, "PBM: DTD has no doc\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000103 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000104 fprintf(output, "PBM: DTD doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000105 if (dtd->prev == NULL) {
106 if ((dtd->parent != NULL) && (dtd->parent->children != (xmlNodePtr)dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000107 fprintf(output, "PBM: DTD has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000108 } else {
109 if (dtd->prev->next != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000110 fprintf(output, "PBM: DTD prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000111 }
112 if (dtd->next == NULL) {
113 if ((dtd->parent != NULL) && (dtd->parent->last != (xmlNodePtr) dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000114 fprintf(output, "PBM: DTD has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000115 } else {
116 if (dtd->next->prev != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000117 fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000118 }
119}
120
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000121static void
122xmlDebugDumpAttrDecl(FILE *output, xmlAttributePtr attr, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000123 int i;
124 char shift[100];
125
126 for (i = 0;((i < depth) && (i < 25));i++)
127 shift[2 * i] = shift[2 * i + 1] = ' ';
128 shift[2 * i] = shift[2 * i + 1] = 0;
129
130 fprintf(output, shift);
131
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000132 if (attr == NULL) {
133 fprintf(output, "Attribute declaration is NULL\n");
134 return;
135 }
Owen Taylor3473f882001-02-23 17:55:21 +0000136 if (attr->type != XML_ATTRIBUTE_DECL) {
137 fprintf(output, "PBM: not a Attr\n");
138 return;
139 }
140 if (attr->name != NULL)
William M. Brack13dfa872004-09-18 04:52:08 +0000141 fprintf(output, "ATTRDECL(%s)", (char *)attr->name);
Owen Taylor3473f882001-02-23 17:55:21 +0000142 else
143 fprintf(output, "PBM ATTRDECL noname!!!");
144 if (attr->elem != NULL)
William M. Brack13dfa872004-09-18 04:52:08 +0000145 fprintf(output, " for %s", (char *)attr->elem);
Owen Taylor3473f882001-02-23 17:55:21 +0000146 else
147 fprintf(output, " PBM noelem!!!");
148 switch (attr->atype) {
149 case XML_ATTRIBUTE_CDATA:
150 fprintf(output, " CDATA");
151 break;
152 case XML_ATTRIBUTE_ID:
153 fprintf(output, " ID");
154 break;
155 case XML_ATTRIBUTE_IDREF:
156 fprintf(output, " IDREF");
157 break;
158 case XML_ATTRIBUTE_IDREFS:
159 fprintf(output, " IDREFS");
160 break;
161 case XML_ATTRIBUTE_ENTITY:
162 fprintf(output, " ENTITY");
163 break;
164 case XML_ATTRIBUTE_ENTITIES:
165 fprintf(output, " ENTITIES");
166 break;
167 case XML_ATTRIBUTE_NMTOKEN:
168 fprintf(output, " NMTOKEN");
169 break;
170 case XML_ATTRIBUTE_NMTOKENS:
171 fprintf(output, " NMTOKENS");
172 break;
173 case XML_ATTRIBUTE_ENUMERATION:
174 fprintf(output, " ENUMERATION");
175 break;
176 case XML_ATTRIBUTE_NOTATION:
177 fprintf(output, " NOTATION ");
178 break;
179 }
180 if (attr->tree != NULL) {
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000181 int indx;
Owen Taylor3473f882001-02-23 17:55:21 +0000182 xmlEnumerationPtr cur = attr->tree;
183
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000184 for (indx = 0;indx < 5; indx++) {
185 if (indx != 0)
William M. Brack13dfa872004-09-18 04:52:08 +0000186 fprintf(output, "|%s", (char *)cur->name);
Owen Taylor3473f882001-02-23 17:55:21 +0000187 else
William M. Brack13dfa872004-09-18 04:52:08 +0000188 fprintf(output, " (%s", (char *)cur->name);
Owen Taylor3473f882001-02-23 17:55:21 +0000189 cur = cur->next;
190 if (cur == NULL) break;
191 }
192 if (cur == NULL)
193 fprintf(output, ")");
194 else
195 fprintf(output, "...)");
196 }
197 switch (attr->def) {
198 case XML_ATTRIBUTE_NONE:
199 break;
200 case XML_ATTRIBUTE_REQUIRED:
201 fprintf(output, " REQUIRED");
202 break;
203 case XML_ATTRIBUTE_IMPLIED:
204 fprintf(output, " IMPLIED");
205 break;
206 case XML_ATTRIBUTE_FIXED:
207 fprintf(output, " FIXED");
208 break;
209 }
210 if (attr->defaultValue != NULL) {
211 fprintf(output, "\"");
212 xmlDebugDumpString(output, attr->defaultValue);
213 fprintf(output, "\"");
214 }
Daniel Veillardcd337f02001-11-22 18:20:37 +0000215 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000216
217 /*
218 * Do a bit of checking
219 */
220 if (attr->parent == NULL)
221 fprintf(output, "PBM: Attr has no parent\n");
222 if (attr->doc == NULL)
223 fprintf(output, "PBM: Attr has no doc\n");
224 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
225 fprintf(output, "PBM: Attr doc differs from parent's one\n");
226 if (attr->prev == NULL) {
227 if ((attr->parent != NULL) && (attr->parent->children != (xmlNodePtr)attr))
228 fprintf(output, "PBM: Attr has no prev and not first of list\n");
229 } else {
230 if (attr->prev->next != (xmlNodePtr) attr)
231 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
232 }
233 if (attr->next == NULL) {
234 if ((attr->parent != NULL) && (attr->parent->last != (xmlNodePtr) attr))
235 fprintf(output, "PBM: Attr has no next and not last of list\n");
236 } else {
237 if (attr->next->prev != (xmlNodePtr) attr)
238 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
239 }
240}
241
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000242static void
243xmlDebugDumpElemDecl(FILE *output, xmlElementPtr elem, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000244 int i;
245 char shift[100];
246
247 for (i = 0;((i < depth) && (i < 25));i++)
248 shift[2 * i] = shift[2 * i + 1] = ' ';
249 shift[2 * i] = shift[2 * i + 1] = 0;
250
251 fprintf(output, shift);
252
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000253 if (elem == NULL) {
254 fprintf(output, "Element declaration is NULL\n");
255 return;
256 }
Owen Taylor3473f882001-02-23 17:55:21 +0000257 if (elem->type != XML_ELEMENT_DECL) {
258 fprintf(output, "PBM: not a Elem\n");
259 return;
260 }
261 if (elem->name != NULL) {
262 fprintf(output, "ELEMDECL(");
263 xmlDebugDumpString(output, elem->name);
264 fprintf(output, ")");
265 } else
266 fprintf(output, "PBM ELEMDECL noname!!!");
267 switch (elem->etype) {
Daniel Veillarda10efa82001-04-18 13:09:01 +0000268 case XML_ELEMENT_TYPE_UNDEFINED:
269 fprintf(output, ", UNDEFINED");
270 break;
Owen Taylor3473f882001-02-23 17:55:21 +0000271 case XML_ELEMENT_TYPE_EMPTY:
272 fprintf(output, ", EMPTY");
273 break;
274 case XML_ELEMENT_TYPE_ANY:
275 fprintf(output, ", ANY");
276 break;
277 case XML_ELEMENT_TYPE_MIXED:
278 fprintf(output, ", MIXED ");
279 break;
280 case XML_ELEMENT_TYPE_ELEMENT:
281 fprintf(output, ", MIXED ");
282 break;
283 }
Daniel Veillard7db37732001-07-12 01:20:08 +0000284 if ((elem->type != XML_ELEMENT_NODE) &&
285 (elem->content != NULL)) {
Owen Taylor3473f882001-02-23 17:55:21 +0000286 char buf[5001];
287
288 buf[0] = 0;
Daniel Veillardd3d06722001-08-15 12:06:36 +0000289 xmlSnprintfElementContent(buf, 5000, elem->content, 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000290 buf[5000] = 0;
291 fprintf(output, "%s", buf);
292 }
Daniel Veillardcd337f02001-11-22 18:20:37 +0000293 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000294
295 /*
296 * Do a bit of checking
297 */
298 if (elem->parent == NULL)
299 fprintf(output, "PBM: Elem has no parent\n");
300 if (elem->doc == NULL)
301 fprintf(output, "PBM: Elem has no doc\n");
302 if ((elem->parent != NULL) && (elem->doc != elem->parent->doc))
303 fprintf(output, "PBM: Elem doc differs from parent's one\n");
304 if (elem->prev == NULL) {
305 if ((elem->parent != NULL) && (elem->parent->children != (xmlNodePtr)elem))
306 fprintf(output, "PBM: Elem has no prev and not first of list\n");
307 } else {
308 if (elem->prev->next != (xmlNodePtr) elem)
309 fprintf(output, "PBM: Elem prev->next : back link wrong\n");
310 }
311 if (elem->next == NULL) {
312 if ((elem->parent != NULL) && (elem->parent->last != (xmlNodePtr) elem))
313 fprintf(output, "PBM: Elem has no next and not last of list\n");
314 } else {
315 if (elem->next->prev != (xmlNodePtr) elem)
316 fprintf(output, "PBM: Elem next->prev : forward link wrong\n");
317 }
318}
319
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000320static void
321xmlDebugDumpEntityDecl(FILE *output, xmlEntityPtr ent, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000322 int i;
323 char shift[100];
324
325 for (i = 0;((i < depth) && (i < 25));i++)
326 shift[2 * i] = shift[2 * i + 1] = ' ';
327 shift[2 * i] = shift[2 * i + 1] = 0;
328
329 fprintf(output, shift);
330
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000331 if (ent == NULL) {
332 fprintf(output, "Entity declaration is NULL\n");
333 return;
334 }
Owen Taylor3473f882001-02-23 17:55:21 +0000335 if (ent->type != XML_ENTITY_DECL) {
336 fprintf(output, "PBM: not a Entity decl\n");
337 return;
338 }
339 if (ent->name != NULL) {
340 fprintf(output, "ENTITYDECL(");
341 xmlDebugDumpString(output, ent->name);
342 fprintf(output, ")");
343 } else
344 fprintf(output, "PBM ENTITYDECL noname!!!");
345 switch (ent->etype) {
346 case XML_INTERNAL_GENERAL_ENTITY:
347 fprintf(output, ", internal\n");
348 break;
349 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
350 fprintf(output, ", external parsed\n");
351 break;
352 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
353 fprintf(output, ", unparsed\n");
354 break;
355 case XML_INTERNAL_PARAMETER_ENTITY:
356 fprintf(output, ", parameter\n");
357 break;
358 case XML_EXTERNAL_PARAMETER_ENTITY:
359 fprintf(output, ", external parameter\n");
360 break;
361 case XML_INTERNAL_PREDEFINED_ENTITY:
362 fprintf(output, ", predefined\n");
363 break;
364 }
365 if (ent->ExternalID) {
366 fprintf(output, shift);
William M. Brack13dfa872004-09-18 04:52:08 +0000367 fprintf(output, " ExternalID=%s\n", (char *)ent->ExternalID);
Owen Taylor3473f882001-02-23 17:55:21 +0000368 }
369 if (ent->SystemID) {
370 fprintf(output, shift);
William M. Brack13dfa872004-09-18 04:52:08 +0000371 fprintf(output, " SystemID=%s\n", (char *)ent->SystemID);
Owen Taylor3473f882001-02-23 17:55:21 +0000372 }
373 if (ent->URI != NULL) {
374 fprintf(output, shift);
William M. Brack13dfa872004-09-18 04:52:08 +0000375 fprintf(output, " URI=%s\n", (char *)ent->URI);
Owen Taylor3473f882001-02-23 17:55:21 +0000376 }
377 if (ent->content) {
378 fprintf(output, shift);
379 fprintf(output, " content=");
380 xmlDebugDumpString(output, ent->content);
381 fprintf(output, "\n");
382 }
383
384 /*
385 * Do a bit of checking
386 */
387 if (ent->parent == NULL)
388 fprintf(output, "PBM: Ent has no parent\n");
389 if (ent->doc == NULL)
390 fprintf(output, "PBM: Ent has no doc\n");
391 if ((ent->parent != NULL) && (ent->doc != ent->parent->doc))
392 fprintf(output, "PBM: Ent doc differs from parent's one\n");
393 if (ent->prev == NULL) {
394 if ((ent->parent != NULL) && (ent->parent->children != (xmlNodePtr)ent))
395 fprintf(output, "PBM: Ent has no prev and not first of list\n");
396 } else {
397 if (ent->prev->next != (xmlNodePtr) ent)
398 fprintf(output, "PBM: Ent prev->next : back link wrong\n");
399 }
400 if (ent->next == NULL) {
401 if ((ent->parent != NULL) && (ent->parent->last != (xmlNodePtr) ent))
402 fprintf(output, "PBM: Ent has no next and not last of list\n");
403 } else {
404 if (ent->next->prev != (xmlNodePtr) ent)
405 fprintf(output, "PBM: Ent next->prev : forward link wrong\n");
406 }
407}
408
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000409static void
410xmlDebugDumpNamespace(FILE *output, xmlNsPtr ns, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000411 int i;
412 char shift[100];
413
414 for (i = 0;((i < depth) && (i < 25));i++)
415 shift[2 * i] = shift[2 * i + 1] = ' ';
416 shift[2 * i] = shift[2 * i + 1] = 0;
417
418 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000419
420 if (ns == NULL) {
421 fprintf(output, "namespace node is NULL\n");
422 return;
423 }
Owen Taylor3473f882001-02-23 17:55:21 +0000424 if (ns->type != XML_NAMESPACE_DECL) {
William M. Brack13dfa872004-09-18 04:52:08 +0000425 fprintf(output, "invalid namespace node %d\n", (char *)ns->type);
Owen Taylor3473f882001-02-23 17:55:21 +0000426 return;
427 }
428 if (ns->href == NULL) {
429 if (ns->prefix != NULL)
William M. Brack13dfa872004-09-18 04:52:08 +0000430 fprintf(output, "incomplete namespace %s href=NULL\n",
431 (char *)ns->prefix);
Owen Taylor3473f882001-02-23 17:55:21 +0000432 else
433 fprintf(output, "incomplete default namespace href=NULL\n");
434 } else {
435 if (ns->prefix != NULL)
William M. Brack13dfa872004-09-18 04:52:08 +0000436 fprintf(output, "namespace %s href=", (char *)ns->prefix);
Owen Taylor3473f882001-02-23 17:55:21 +0000437 else
438 fprintf(output, "default namespace href=");
439
440 xmlDebugDumpString(output, ns->href);
441 fprintf(output, "\n");
442 }
443}
444
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000445static void
446xmlDebugDumpNamespaceList(FILE *output, xmlNsPtr ns, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000447 while (ns != NULL) {
448 xmlDebugDumpNamespace(output, ns, depth);
449 ns = ns->next;
450 }
451}
452
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000453static void
454xmlDebugDumpEntity(FILE *output, xmlEntityPtr ent, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000455 int i;
456 char shift[100];
457
458 for (i = 0;((i < depth) && (i < 25));i++)
459 shift[2 * i] = shift[2 * i + 1] = ' ';
460 shift[2 * i] = shift[2 * i + 1] = 0;
461
462 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000463
464 if (ent == NULL) {
465 fprintf(output, "Entity is NULL\n");
466 return;
467 }
Owen Taylor3473f882001-02-23 17:55:21 +0000468 switch (ent->etype) {
469 case XML_INTERNAL_GENERAL_ENTITY:
470 fprintf(output, "INTERNAL_GENERAL_ENTITY ");
471 break;
472 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
473 fprintf(output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
474 break;
475 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
476 fprintf(output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
477 break;
478 case XML_INTERNAL_PARAMETER_ENTITY:
479 fprintf(output, "INTERNAL_PARAMETER_ENTITY ");
480 break;
481 case XML_EXTERNAL_PARAMETER_ENTITY:
482 fprintf(output, "EXTERNAL_PARAMETER_ENTITY ");
483 break;
484 default:
William M. Brack13dfa872004-09-18 04:52:08 +0000485 fprintf(output, "ENTITY_%d ! ", (char *)ent->etype);
Owen Taylor3473f882001-02-23 17:55:21 +0000486 }
487 fprintf(output, "%s\n", ent->name);
488 if (ent->ExternalID) {
489 fprintf(output, shift);
William M. Brack13dfa872004-09-18 04:52:08 +0000490 fprintf(output, "ExternalID=%s\n", (char *)ent->ExternalID);
Owen Taylor3473f882001-02-23 17:55:21 +0000491 }
492 if (ent->SystemID) {
493 fprintf(output, shift);
William M. Brack13dfa872004-09-18 04:52:08 +0000494 fprintf(output, "SystemID=%s\n", (char *)ent->SystemID);
Owen Taylor3473f882001-02-23 17:55:21 +0000495 }
496 if (ent->URI) {
497 fprintf(output, shift);
William M. Brack13dfa872004-09-18 04:52:08 +0000498 fprintf(output, "URI=%s\n", (char *)ent->URI);
Owen Taylor3473f882001-02-23 17:55:21 +0000499 }
500 if (ent->content) {
501 fprintf(output, shift);
502 fprintf(output, "content=");
503 xmlDebugDumpString(output, ent->content);
504 fprintf(output, "\n");
505 }
506}
507
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000508/**
509 * xmlDebugDumpAttr:
510 * @output: the FILE * for the output
511 * @attr: the attribute
512 * @depth: the indentation level.
513 *
514 * Dumps debug information for the attribute
515 */
516void
517xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
Owen Taylor3473f882001-02-23 17:55:21 +0000518 int i;
519 char shift[100];
520
521 for (i = 0;((i < depth) && (i < 25));i++)
522 shift[2 * i] = shift[2 * i + 1] = ' ';
523 shift[2 * i] = shift[2 * i + 1] = 0;
524
525 fprintf(output, shift);
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000526
527 if (attr == NULL) {
528 fprintf(output, "Attr is NULL");
529 return;
530 }
Owen Taylor3473f882001-02-23 17:55:21 +0000531 fprintf(output, "ATTRIBUTE ");
532 xmlDebugDumpString(output, attr->name);
533 fprintf(output, "\n");
534 if (attr->children != NULL)
535 xmlDebugDumpNodeList(output, attr->children, depth + 1);
536
537 /*
538 * Do a bit of checking
539 */
540 if (attr->parent == NULL)
541 fprintf(output, "PBM: Attr has no parent\n");
542 if (attr->doc == NULL)
543 fprintf(output, "PBM: Attr has no doc\n");
544 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
545 fprintf(output, "PBM: Attr doc differs from parent's one\n");
546 if (attr->prev == NULL) {
547 if ((attr->parent != NULL) && (attr->parent->properties != attr))
548 fprintf(output, "PBM: Attr has no prev and not first of list\n");
549 } else {
550 if (attr->prev->next != attr)
551 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
552 }
553 if (attr->next != NULL) {
554 if (attr->next->prev != attr)
555 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
556 }
557}
558
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000559/**
560 * xmlDebugDumpAttrList:
561 * @output: the FILE * for the output
562 * @attr: the attribute list
563 * @depth: the indentation level.
564 *
565 * Dumps debug information for the attribute list
566 */
567void
568xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth)
569{
Daniel Veillard7db38712002-02-07 16:39:11 +0000570 if (output == NULL)
571 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000572 while (attr != NULL) {
573 xmlDebugDumpAttr(output, attr, depth);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000574 attr = attr->next;
Owen Taylor3473f882001-02-23 17:55:21 +0000575 }
576}
577
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000578/**
579 * xmlDebugDumpOneNode:
580 * @output: the FILE * for the output
581 * @node: the node
582 * @depth: the indentation level.
583 *
584 * Dumps debug information for the element node, it is not recursive
585 */
586void
587xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth)
588{
Owen Taylor3473f882001-02-23 17:55:21 +0000589 int i;
590 char shift[100];
591
Daniel Veillard7db38712002-02-07 16:39:11 +0000592 if (output == NULL)
593 output = stdout;
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000594 for (i = 0; ((i < depth) && (i < 25)); i++)
Owen Taylor3473f882001-02-23 17:55:21 +0000595 shift[2 * i] = shift[2 * i + 1] = ' ';
596 shift[2 * i] = shift[2 * i + 1] = 0;
597
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000598 if (node == NULL) {
599 fprintf(output, shift);
600 fprintf(output, "node is NULL\n");
601 return;
602 }
Owen Taylor3473f882001-02-23 17:55:21 +0000603 switch (node->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000604 case XML_ELEMENT_NODE:
605 fprintf(output, shift);
606 fprintf(output, "ELEMENT ");
607 if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
608 xmlDebugDumpString(output, node->ns->prefix);
609 fprintf(output, ":");
610 }
611 xmlDebugDumpString(output, node->name);
612 fprintf(output, "\n");
613 break;
614 case XML_ATTRIBUTE_NODE:
615 fprintf(output, shift);
616 fprintf(output, "Error, ATTRIBUTE found here\n");
617 break;
618 case XML_TEXT_NODE:
619 fprintf(output, shift);
Daniel Veillardb44025c2001-10-11 22:55:55 +0000620 if (node->name == (const xmlChar *) xmlStringTextNoenc)
Daniel Veillard567e1b42001-08-01 15:53:47 +0000621 fprintf(output, "TEXT no enc\n");
622 else
623 fprintf(output, "TEXT\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000624 break;
625 case XML_CDATA_SECTION_NODE:
626 fprintf(output, shift);
627 fprintf(output, "CDATA_SECTION\n");
628 break;
629 case XML_ENTITY_REF_NODE:
630 fprintf(output, shift);
William M. Brack13dfa872004-09-18 04:52:08 +0000631 fprintf(output, "ENTITY_REF(%s)\n", (char *)node->name);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000632 break;
633 case XML_ENTITY_NODE:
634 fprintf(output, shift);
635 fprintf(output, "ENTITY\n");
636 break;
637 case XML_PI_NODE:
638 fprintf(output, shift);
William M. Brack13dfa872004-09-18 04:52:08 +0000639 fprintf(output, "PI %s\n", (char *)node->name);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000640 break;
641 case XML_COMMENT_NODE:
642 fprintf(output, shift);
643 fprintf(output, "COMMENT\n");
644 break;
645 case XML_DOCUMENT_NODE:
646 case XML_HTML_DOCUMENT_NODE:
647 fprintf(output, shift);
648 fprintf(output, "Error, DOCUMENT found here\n");
649 break;
650 case XML_DOCUMENT_TYPE_NODE:
651 fprintf(output, shift);
652 fprintf(output, "DOCUMENT_TYPE\n");
653 break;
654 case XML_DOCUMENT_FRAG_NODE:
655 fprintf(output, shift);
656 fprintf(output, "DOCUMENT_FRAG\n");
657 break;
658 case XML_NOTATION_NODE:
659 fprintf(output, shift);
660 fprintf(output, "NOTATION\n");
661 break;
662 case XML_DTD_NODE:
663 xmlDebugDumpDtdNode(output, (xmlDtdPtr) node, depth);
664 return;
665 case XML_ELEMENT_DECL:
666 xmlDebugDumpElemDecl(output, (xmlElementPtr) node, depth);
667 return;
668 case XML_ATTRIBUTE_DECL:
669 xmlDebugDumpAttrDecl(output, (xmlAttributePtr) node, depth);
670 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000671 case XML_ENTITY_DECL:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000672 xmlDebugDumpEntityDecl(output, (xmlEntityPtr) node, depth);
673 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000674 case XML_NAMESPACE_DECL:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000675 xmlDebugDumpNamespace(output, (xmlNsPtr) node, depth);
676 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000677 case XML_XINCLUDE_START:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000678 fprintf(output, shift);
679 fprintf(output, "INCLUDE START\n");
680 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000681 case XML_XINCLUDE_END:
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000682 fprintf(output, shift);
683 fprintf(output, "INCLUDE END\n");
684 return;
685 default:
686 fprintf(output, shift);
William M. Brack13dfa872004-09-18 04:52:08 +0000687 fprintf(output, "NODE_%d !!!\n", (char *)node->type);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000688 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000689 }
690 if (node->doc == NULL) {
691 fprintf(output, shift);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000692 fprintf(output, "doc == NULL !!!\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000693 }
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000694 if (node->nsDef != NULL)
Owen Taylor3473f882001-02-23 17:55:21 +0000695 xmlDebugDumpNamespaceList(output, node->nsDef, depth + 1);
696 if (node->properties != NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000697 xmlDebugDumpAttrList(output, node->properties, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000698 if (node->type != XML_ENTITY_REF_NODE) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000699 if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
700 shift[2 * i] = shift[2 * i + 1] = ' ';
701 shift[2 * i + 2] = shift[2 * i + 3] = 0;
702 fprintf(output, shift);
703 fprintf(output, "content=");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000704 xmlDebugDumpString(output, node->content);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000705 fprintf(output, "\n");
706 }
Owen Taylor3473f882001-02-23 17:55:21 +0000707 } else {
708 xmlEntityPtr ent;
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000709
710 ent = xmlGetDocEntity(node->doc, node->name);
711 if (ent != NULL)
712 xmlDebugDumpEntity(output, ent, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000713 }
714 /*
715 * Do a bit of checking
716 */
717 if (node->parent == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000718 fprintf(output, "PBM: Node has no parent\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000719 if (node->doc == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000720 fprintf(output, "PBM: Node has no doc\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000721 if ((node->parent != NULL) && (node->doc != node->parent->doc))
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000722 fprintf(output, "PBM: Node doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000723 if (node->prev == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000724 if ((node->parent != NULL) && (node->parent->children != node))
725 fprintf(output,
726 "PBM: Node has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000727 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000728 if (node->prev->next != node)
729 fprintf(output, "PBM: Node prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000730 }
731 if (node->next == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000732 if ((node->parent != NULL) && (node->parent->last != node))
733 fprintf(output,
734 "PBM: Node has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000735 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000736 if (node->next->prev != node)
737 fprintf(output, "PBM: Node next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000738 }
739}
740
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000741/**
742 * xmlDebugDumpNode:
743 * @output: the FILE * for the output
744 * @node: the node
745 * @depth: the indentation level.
746 *
747 * Dumps debug information for the element node, it is recursive
748 */
749void
750xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth)
751{
Daniel Veillard7db38712002-02-07 16:39:11 +0000752 if (output == NULL)
753 output = stdout;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000754 if (node == NULL) {
755 int i;
756 char shift[100];
757
758 for (i = 0; ((i < depth) && (i < 25)); i++)
759 shift[2 * i] = shift[2 * i + 1] = ' ';
760 shift[2 * i] = shift[2 * i + 1] = 0;
761
762 fprintf(output, shift);
763 fprintf(output, "node is NULL\n");
764 return;
765 }
Owen Taylor3473f882001-02-23 17:55:21 +0000766 xmlDebugDumpOneNode(output, node, depth);
767 if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE))
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000768 xmlDebugDumpNodeList(output, node->children, depth + 1);
Owen Taylor3473f882001-02-23 17:55:21 +0000769}
770
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000771/**
772 * xmlDebugDumpNodeList:
773 * @output: the FILE * for the output
774 * @node: the node list
775 * @depth: the indentation level.
776 *
777 * Dumps debug information for the list of element node, it is recursive
778 */
779void
780xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth)
781{
Daniel Veillard7db38712002-02-07 16:39:11 +0000782 if (output == NULL)
783 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000784 while (node != NULL) {
785 xmlDebugDumpNode(output, node, depth);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000786 node = node->next;
Owen Taylor3473f882001-02-23 17:55:21 +0000787 }
788}
789
790
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000791/**
792 * xmlDebugDumpDocumentHead:
793 * @output: the FILE * for the output
794 * @doc: the document
795 *
796 * Dumps debug information cncerning the document, not recursive
797 */
798void
799xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc)
800{
801 if (output == NULL)
802 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000803 if (doc == NULL) {
804 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000805 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000806 }
807
808 switch (doc->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000809 case XML_ELEMENT_NODE:
810 fprintf(output, "Error, ELEMENT found here ");
811 break;
812 case XML_ATTRIBUTE_NODE:
813 fprintf(output, "Error, ATTRIBUTE found here\n");
814 break;
815 case XML_TEXT_NODE:
816 fprintf(output, "Error, TEXT\n");
817 break;
818 case XML_CDATA_SECTION_NODE:
819 fprintf(output, "Error, CDATA_SECTION\n");
820 break;
821 case XML_ENTITY_REF_NODE:
822 fprintf(output, "Error, ENTITY_REF\n");
823 break;
824 case XML_ENTITY_NODE:
825 fprintf(output, "Error, ENTITY\n");
826 break;
827 case XML_PI_NODE:
828 fprintf(output, "Error, PI\n");
829 break;
830 case XML_COMMENT_NODE:
831 fprintf(output, "Error, COMMENT\n");
832 break;
833 case XML_DOCUMENT_NODE:
834 fprintf(output, "DOCUMENT\n");
835 break;
836 case XML_HTML_DOCUMENT_NODE:
837 fprintf(output, "HTML DOCUMENT\n");
838 break;
839 case XML_DOCUMENT_TYPE_NODE:
840 fprintf(output, "Error, DOCUMENT_TYPE\n");
841 break;
842 case XML_DOCUMENT_FRAG_NODE:
843 fprintf(output, "Error, DOCUMENT_FRAG\n");
844 break;
845 case XML_NOTATION_NODE:
846 fprintf(output, "Error, NOTATION\n");
847 break;
848 default:
William M. Brack13dfa872004-09-18 04:52:08 +0000849 fprintf(output, "NODE_%d\n", (char *)doc->type);
Owen Taylor3473f882001-02-23 17:55:21 +0000850 }
851 if (doc->name != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000852 fprintf(output, "name=");
Owen Taylor3473f882001-02-23 17:55:21 +0000853 xmlDebugDumpString(output, BAD_CAST doc->name);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000854 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000855 }
856 if (doc->version != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000857 fprintf(output, "version=");
Owen Taylor3473f882001-02-23 17:55:21 +0000858 xmlDebugDumpString(output, doc->version);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000859 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000860 }
861 if (doc->encoding != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000862 fprintf(output, "encoding=");
Owen Taylor3473f882001-02-23 17:55:21 +0000863 xmlDebugDumpString(output, doc->encoding);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000864 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000865 }
866 if (doc->URL != NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000867 fprintf(output, "URL=");
Owen Taylor3473f882001-02-23 17:55:21 +0000868 xmlDebugDumpString(output, doc->URL);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000869 fprintf(output, "\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000870 }
871 if (doc->standalone)
872 fprintf(output, "standalone=true\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000873 if (doc->oldNs != NULL)
Owen Taylor3473f882001-02-23 17:55:21 +0000874 xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
875}
876
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000877/**
878 * xmlDebugDumpDocument:
879 * @output: the FILE * for the output
880 * @doc: the document
881 *
882 * Dumps debug information for the document, it's recursive
883 */
884void
885xmlDebugDumpDocument(FILE * output, xmlDocPtr doc)
886{
887 if (output == NULL)
888 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +0000889 if (doc == NULL) {
890 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000891 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000892 }
893 xmlDebugDumpDocumentHead(output, doc);
894 if (((doc->type == XML_DOCUMENT_NODE) ||
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000895 (doc->type == XML_HTML_DOCUMENT_NODE)) && (doc->children != NULL))
Owen Taylor3473f882001-02-23 17:55:21 +0000896 xmlDebugDumpNodeList(output, doc->children, 1);
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000897}
Owen Taylor3473f882001-02-23 17:55:21 +0000898
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000899/**
900 * xmlDebugDumpDTD:
901 * @output: the FILE * for the output
902 * @dtd: the DTD
903 *
904 * Dumps debug information for the DTD
905 */
906void
907xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd)
908{
Daniel Veillard7db38712002-02-07 16:39:11 +0000909 if (output == NULL)
910 output = stdout;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000911 if (dtd == NULL) {
912 fprintf(output, "DTD is NULL\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000913 return;
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000914 }
Owen Taylor3473f882001-02-23 17:55:21 +0000915 if (dtd->type != XML_DTD_NODE) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000916 fprintf(output, "PBM: not a DTD\n");
917 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000918 }
919 if (dtd->name != NULL)
William M. Brack13dfa872004-09-18 04:52:08 +0000920 fprintf(output, "DTD(%s)", (char *)dtd->name);
Owen Taylor3473f882001-02-23 17:55:21 +0000921 else
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000922 fprintf(output, "DTD");
Owen Taylor3473f882001-02-23 17:55:21 +0000923 if (dtd->ExternalID != NULL)
William M. Brack13dfa872004-09-18 04:52:08 +0000924 fprintf(output, ", PUBLIC %s", (char *)dtd->ExternalID);
Owen Taylor3473f882001-02-23 17:55:21 +0000925 if (dtd->SystemID != NULL)
William M. Brack13dfa872004-09-18 04:52:08 +0000926 fprintf(output, ", SYSTEM %s", (char *)dtd->SystemID);
Owen Taylor3473f882001-02-23 17:55:21 +0000927 fprintf(output, "\n");
928 /*
929 * Do a bit of checking
930 */
931 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000932 fprintf(output, "PBM: DTD doc differs from parent's one\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000933 if (dtd->prev == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000934 if ((dtd->parent != NULL)
935 && (dtd->parent->children != (xmlNodePtr) dtd))
936 fprintf(output,
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000937 "PBM: DTD has no prev and not first of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000938 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000939 if (dtd->prev->next != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000940 fprintf(output, "PBM: DTD prev->next : back link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000941 }
942 if (dtd->next == NULL) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000943 if ((dtd->parent != NULL)
944 && (dtd->parent->last != (xmlNodePtr) dtd))
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000945 fprintf(output, "PBM: DTD has no next and not last of list\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000946 } else {
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000947 if (dtd->next->prev != (xmlNodePtr) dtd)
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000948 fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000949 }
950 if (dtd->children == NULL)
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000951 fprintf(output, " DTD is empty\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000952 else
953 xmlDebugDumpNodeList(output, dtd->children, 1);
954}
955
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000956static void
957xmlDebugDumpEntityCallback(xmlEntityPtr cur, FILE *output) {
Daniel Veillard5e926fa2002-01-22 21:44:25 +0000958 if (cur == NULL) {
959 fprintf(output, "Entity is NULL");
960 return;
961 }
William M. Brack13dfa872004-09-18 04:52:08 +0000962 fprintf(output, "%s : ", (char *)cur->name);
Owen Taylor3473f882001-02-23 17:55:21 +0000963 switch (cur->etype) {
964 case XML_INTERNAL_GENERAL_ENTITY:
965 fprintf(output, "INTERNAL GENERAL, ");
966 break;
967 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
968 fprintf(output, "EXTERNAL PARSED, ");
969 break;
970 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
971 fprintf(output, "EXTERNAL UNPARSED, ");
972 break;
973 case XML_INTERNAL_PARAMETER_ENTITY:
974 fprintf(output, "INTERNAL PARAMETER, ");
975 break;
976 case XML_EXTERNAL_PARAMETER_ENTITY:
977 fprintf(output, "EXTERNAL PARAMETER, ");
978 break;
979 default:
980 fprintf(output, "UNKNOWN TYPE %d",
William M. Brack13dfa872004-09-18 04:52:08 +0000981 (char *)cur->etype);
Owen Taylor3473f882001-02-23 17:55:21 +0000982 }
983 if (cur->ExternalID != NULL)
William M. Brack13dfa872004-09-18 04:52:08 +0000984 fprintf(output, "ID \"%s\"", (char *)cur->ExternalID);
Owen Taylor3473f882001-02-23 17:55:21 +0000985 if (cur->SystemID != NULL)
William M. Brack13dfa872004-09-18 04:52:08 +0000986 fprintf(output, "SYSTEM \"%s\"", (char *)cur->SystemID);
Owen Taylor3473f882001-02-23 17:55:21 +0000987 if (cur->orig != NULL)
William M. Brack13dfa872004-09-18 04:52:08 +0000988 fprintf(output, "\n orig \"%s\"", (char *)cur->orig);
Daniel Veillard7db37732001-07-12 01:20:08 +0000989 if ((cur->type != XML_ELEMENT_NODE) &&
990 (cur->content != NULL))
William M. Brack13dfa872004-09-18 04:52:08 +0000991 fprintf(output, "\n content \"%s\"", (char *)cur->content);
Owen Taylor3473f882001-02-23 17:55:21 +0000992 fprintf(output, "\n");
993}
994
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000995/**
996 * xmlDebugDumpEntities:
997 * @output: the FILE * for the output
998 * @doc: the document
999 *
1000 * Dumps debug information for all the entities in use by the document
1001 */
1002void
1003xmlDebugDumpEntities(FILE * output, xmlDocPtr doc)
1004{
1005 if (output == NULL)
1006 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +00001007 if (doc == NULL) {
1008 fprintf(output, "DOCUMENT == NULL !\n");
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001009 return;
Owen Taylor3473f882001-02-23 17:55:21 +00001010 }
1011
1012 switch (doc->type) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001013 case XML_ELEMENT_NODE:
1014 fprintf(output, "Error, ELEMENT found here ");
1015 break;
1016 case XML_ATTRIBUTE_NODE:
1017 fprintf(output, "Error, ATTRIBUTE found here\n");
1018 break;
1019 case XML_TEXT_NODE:
1020 fprintf(output, "Error, TEXT\n");
1021 break;
1022 case XML_CDATA_SECTION_NODE:
1023 fprintf(output, "Error, CDATA_SECTION\n");
1024 break;
1025 case XML_ENTITY_REF_NODE:
1026 fprintf(output, "Error, ENTITY_REF\n");
1027 break;
1028 case XML_ENTITY_NODE:
1029 fprintf(output, "Error, ENTITY\n");
1030 break;
1031 case XML_PI_NODE:
1032 fprintf(output, "Error, PI\n");
1033 break;
1034 case XML_COMMENT_NODE:
1035 fprintf(output, "Error, COMMENT\n");
1036 break;
1037 case XML_DOCUMENT_NODE:
1038 fprintf(output, "DOCUMENT\n");
1039 break;
1040 case XML_HTML_DOCUMENT_NODE:
1041 fprintf(output, "HTML DOCUMENT\n");
1042 break;
1043 case XML_DOCUMENT_TYPE_NODE:
1044 fprintf(output, "Error, DOCUMENT_TYPE\n");
1045 break;
1046 case XML_DOCUMENT_FRAG_NODE:
1047 fprintf(output, "Error, DOCUMENT_FRAG\n");
1048 break;
1049 case XML_NOTATION_NODE:
1050 fprintf(output, "Error, NOTATION\n");
1051 break;
1052 default:
William M. Brack13dfa872004-09-18 04:52:08 +00001053 fprintf(output, "NODE_%d\n", (char *)doc->type);
Owen Taylor3473f882001-02-23 17:55:21 +00001054 }
1055 if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001056 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1057 doc->intSubset->entities;
1058
1059 fprintf(output, "Entities in internal subset\n");
1060 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1061 output);
Owen Taylor3473f882001-02-23 17:55:21 +00001062 } else
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001063 fprintf(output, "No entities in internal subset\n");
Owen Taylor3473f882001-02-23 17:55:21 +00001064 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001065 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1066 doc->extSubset->entities;
1067
1068 fprintf(output, "Entities in external subset\n");
1069 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1070 output);
Owen Taylor3473f882001-02-23 17:55:21 +00001071 } else
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001072 fprintf(output, "No entities in external subset\n");
Owen Taylor3473f882001-02-23 17:55:21 +00001073}
1074
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001075/**
1076 * xmlLsCountNode:
1077 * @node: the node to count
1078 *
1079 * Count the children of @node.
1080 *
1081 * Returns the number of children of @node.
1082 */
1083int
1084xmlLsCountNode(xmlNodePtr node) {
Owen Taylor3473f882001-02-23 17:55:21 +00001085 int ret = 0;
1086 xmlNodePtr list = NULL;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001087
1088 if (node == NULL)
1089 return(0);
Owen Taylor3473f882001-02-23 17:55:21 +00001090
1091 switch (node->type) {
1092 case XML_ELEMENT_NODE:
1093 list = node->children;
1094 break;
1095 case XML_DOCUMENT_NODE:
1096 case XML_HTML_DOCUMENT_NODE:
Daniel Veillardeae522a2001-04-23 13:41:34 +00001097#ifdef LIBXML_DOCB_ENABLED
1098 case XML_DOCB_DOCUMENT_NODE:
Owen Taylor3473f882001-02-23 17:55:21 +00001099#endif
1100 list = ((xmlDocPtr) node)->children;
1101 break;
1102 case XML_ATTRIBUTE_NODE:
1103 list = ((xmlAttrPtr) node)->children;
1104 break;
1105 case XML_TEXT_NODE:
1106 case XML_CDATA_SECTION_NODE:
1107 case XML_PI_NODE:
1108 case XML_COMMENT_NODE:
1109 if (node->content != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001110 ret = xmlStrlen(node->content);
Owen Taylor3473f882001-02-23 17:55:21 +00001111 }
1112 break;
1113 case XML_ENTITY_REF_NODE:
1114 case XML_DOCUMENT_TYPE_NODE:
1115 case XML_ENTITY_NODE:
1116 case XML_DOCUMENT_FRAG_NODE:
1117 case XML_NOTATION_NODE:
1118 case XML_DTD_NODE:
1119 case XML_ELEMENT_DECL:
1120 case XML_ATTRIBUTE_DECL:
1121 case XML_ENTITY_DECL:
1122 case XML_NAMESPACE_DECL:
1123 case XML_XINCLUDE_START:
1124 case XML_XINCLUDE_END:
1125 ret = 1;
1126 break;
1127 }
1128 for (;list != NULL;ret++)
1129 list = list->next;
1130 return(ret);
1131}
1132
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001133/**
1134 * xmlLsOneNode:
1135 * @output: the FILE * for the output
1136 * @node: the node to dump
1137 *
1138 * Dump to @output the type and name of @node.
1139 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001140void
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001141xmlLsOneNode(FILE *output, xmlNodePtr node) {
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001142 if (node == NULL) {
1143 fprintf(output, "NULL\n");
1144 return;
1145 }
Owen Taylor3473f882001-02-23 17:55:21 +00001146 switch (node->type) {
1147 case XML_ELEMENT_NODE:
1148 fprintf(output, "-");
1149 break;
1150 case XML_ATTRIBUTE_NODE:
1151 fprintf(output, "a");
1152 break;
1153 case XML_TEXT_NODE:
1154 fprintf(output, "t");
1155 break;
1156 case XML_CDATA_SECTION_NODE:
Daniel Veillard75be0132002-03-13 10:03:35 +00001157 fprintf(output, "C");
Owen Taylor3473f882001-02-23 17:55:21 +00001158 break;
1159 case XML_ENTITY_REF_NODE:
1160 fprintf(output, "e");
1161 break;
1162 case XML_ENTITY_NODE:
1163 fprintf(output, "E");
1164 break;
1165 case XML_PI_NODE:
1166 fprintf(output, "p");
1167 break;
1168 case XML_COMMENT_NODE:
1169 fprintf(output, "c");
1170 break;
1171 case XML_DOCUMENT_NODE:
1172 fprintf(output, "d");
1173 break;
1174 case XML_HTML_DOCUMENT_NODE:
1175 fprintf(output, "h");
1176 break;
1177 case XML_DOCUMENT_TYPE_NODE:
1178 fprintf(output, "T");
1179 break;
1180 case XML_DOCUMENT_FRAG_NODE:
1181 fprintf(output, "F");
1182 break;
1183 case XML_NOTATION_NODE:
1184 fprintf(output, "N");
1185 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001186 case XML_NAMESPACE_DECL:
1187 fprintf(output, "n");
1188 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001189 default:
1190 fprintf(output, "?");
1191 }
Daniel Veillarde6a55192002-01-14 17:11:53 +00001192 if (node->type != XML_NAMESPACE_DECL) {
1193 if (node->properties != NULL)
1194 fprintf(output, "a");
1195 else
1196 fprintf(output, "-");
1197 if (node->nsDef != NULL)
1198 fprintf(output, "n");
1199 else
1200 fprintf(output, "-");
1201 }
Owen Taylor3473f882001-02-23 17:55:21 +00001202
1203 fprintf(output, " %8d ", xmlLsCountNode(node));
1204
1205 switch (node->type) {
1206 case XML_ELEMENT_NODE:
1207 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001208 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001209 break;
1210 case XML_ATTRIBUTE_NODE:
1211 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001212 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001213 break;
1214 case XML_TEXT_NODE:
1215 if (node->content != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001216 xmlDebugDumpString(output, node->content);
Owen Taylor3473f882001-02-23 17:55:21 +00001217 }
1218 break;
1219 case XML_CDATA_SECTION_NODE:
1220 break;
1221 case XML_ENTITY_REF_NODE:
1222 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001223 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001224 break;
1225 case XML_ENTITY_NODE:
1226 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001227 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001228 break;
1229 case XML_PI_NODE:
1230 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001231 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001232 break;
1233 case XML_COMMENT_NODE:
1234 break;
1235 case XML_DOCUMENT_NODE:
1236 break;
1237 case XML_HTML_DOCUMENT_NODE:
1238 break;
1239 case XML_DOCUMENT_TYPE_NODE:
1240 break;
1241 case XML_DOCUMENT_FRAG_NODE:
1242 break;
1243 case XML_NOTATION_NODE:
1244 break;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001245 case XML_NAMESPACE_DECL: {
1246 xmlNsPtr ns = (xmlNsPtr) node;
1247
1248 if (ns->prefix == NULL)
William M. Brack13dfa872004-09-18 04:52:08 +00001249 fprintf(output, "default -> %s", (char *)ns->href);
Daniel Veillarde6a55192002-01-14 17:11:53 +00001250 else
William M. Brack13dfa872004-09-18 04:52:08 +00001251 fprintf(output, "%s -> %s", (char *)ns->prefix,
1252 (char *)ns->href);
Daniel Veillarde6a55192002-01-14 17:11:53 +00001253 break;
1254 }
Owen Taylor3473f882001-02-23 17:55:21 +00001255 default:
1256 if (node->name != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001257 fprintf(output, "%s", (const char *) node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00001258 }
1259 fprintf(output, "\n");
1260}
1261
Daniel Veillard78d12092001-10-11 09:12:24 +00001262/**
1263 * xmlBoolToText:
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001264 * @boolval: a bool to turn into text
Daniel Veillard78d12092001-10-11 09:12:24 +00001265 *
1266 * Convenient way to turn bool into text
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001267 *
1268 * Returns a pointer to either "True" or "False"
1269 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001270const char *
Daniel Veillardebd38c52001-11-01 08:38:12 +00001271xmlBoolToText(int boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001272{
Daniel Veillardebd38c52001-11-01 08:38:12 +00001273 if (boolval)
Daniel Veillard78d12092001-10-11 09:12:24 +00001274 return("True");
1275 else
1276 return("False");
1277}
1278
Owen Taylor3473f882001-02-23 17:55:21 +00001279/****************************************************************
1280 * *
1281 * The XML shell related functions *
1282 * *
1283 ****************************************************************/
1284
Daniel Veillard78d12092001-10-11 09:12:24 +00001285
1286
Owen Taylor3473f882001-02-23 17:55:21 +00001287/*
1288 * TODO: Improvement/cleanups for the XML shell
1289 * - allow to shell out an editor on a subpart
1290 * - cleanup function registrations (with help) and calling
1291 * - provide registration routines
1292 */
1293
1294/**
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001295 * xmlShellPrintXPathError:
Daniel Veillard78d12092001-10-11 09:12:24 +00001296 * @errorType: valid xpath error id
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001297 * @arg: the argument that cause xpath to fail
Daniel Veillard78d12092001-10-11 09:12:24 +00001298 *
1299 * Print the xpath error to libxml default error channel
1300 */
1301void
1302xmlShellPrintXPathError(int errorType, const char *arg)
1303{
1304 const char *default_arg = "Result";
1305
1306 if (!arg)
1307 arg = default_arg;
1308
1309 switch (errorType) {
1310 case XPATH_UNDEFINED:
1311 xmlGenericError(xmlGenericErrorContext,
1312 "%s: no such node\n", arg);
1313 break;
1314
1315 case XPATH_BOOLEAN:
1316 xmlGenericError(xmlGenericErrorContext,
1317 "%s is a Boolean\n", arg);
1318 break;
1319 case XPATH_NUMBER:
1320 xmlGenericError(xmlGenericErrorContext,
1321 "%s is a number\n", arg);
1322 break;
1323 case XPATH_STRING:
1324 xmlGenericError(xmlGenericErrorContext,
1325 "%s is a string\n", arg);
1326 break;
1327 case XPATH_POINT:
1328 xmlGenericError(xmlGenericErrorContext,
1329 "%s is a point\n", arg);
1330 break;
1331 case XPATH_RANGE:
1332 xmlGenericError(xmlGenericErrorContext,
1333 "%s is a range\n", arg);
1334 break;
1335 case XPATH_LOCATIONSET:
1336 xmlGenericError(xmlGenericErrorContext,
1337 "%s is a range\n", arg);
1338 break;
1339 case XPATH_USERS:
1340 xmlGenericError(xmlGenericErrorContext,
1341 "%s is user-defined\n", arg);
1342 break;
1343 case XPATH_XSLT_TREE:
1344 xmlGenericError(xmlGenericErrorContext,
1345 "%s is an XSLT value tree\n", arg);
1346 break;
1347 }
1348 xmlGenericError(xmlGenericErrorContext,
1349 "Try casting the result string function (xpath builtin)\n",
1350 arg);
1351}
1352
1353
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001354#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001355/**
Daniel Veillard321be0c2002-10-08 21:26:42 +00001356 * xmlShellPrintNodeCtxt:
1357 * @ctxt : a non-null shell context
1358 * @node : a non-null node to print to the output FILE
Daniel Veillard78d12092001-10-11 09:12:24 +00001359 *
Daniel Veillard321be0c2002-10-08 21:26:42 +00001360 * Print node to the output FILE
1361 */
1362static void
1363xmlShellPrintNodeCtxt(xmlShellCtxtPtr ctxt,xmlNodePtr node)
1364{
Daniel Veillard01992e02002-10-09 10:20:30 +00001365 FILE *fp;
1366
1367 if (!node)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001368 return;
Daniel Veillard01992e02002-10-09 10:20:30 +00001369 if (ctxt == NULL)
1370 fp = stdout;
1371 else
1372 fp = ctxt->output;
Daniel Veillard321be0c2002-10-08 21:26:42 +00001373
1374 if (node->type == XML_DOCUMENT_NODE)
Daniel Veillard01992e02002-10-09 10:20:30 +00001375 xmlDocDump(fp, (xmlDocPtr) node);
Daniel Veillard321be0c2002-10-08 21:26:42 +00001376 else if (node->type == XML_ATTRIBUTE_NODE)
Daniel Veillard01992e02002-10-09 10:20:30 +00001377 xmlDebugDumpAttrList(fp, (xmlAttrPtr) node, 0);
Daniel Veillard321be0c2002-10-08 21:26:42 +00001378 else
Daniel Veillard01992e02002-10-09 10:20:30 +00001379 xmlElemDump(fp, node->doc, node);
Daniel Veillard321be0c2002-10-08 21:26:42 +00001380
Daniel Veillard01992e02002-10-09 10:20:30 +00001381 fprintf(fp, "\n");
Daniel Veillard321be0c2002-10-08 21:26:42 +00001382}
1383
1384/**
1385 * xmlShellPrintNode:
1386 * @node : a non-null node to print to the output FILE
1387 *
1388 * Print node to the output FILE
Daniel Veillard78d12092001-10-11 09:12:24 +00001389 */
1390void
1391xmlShellPrintNode(xmlNodePtr node)
1392{
Daniel Veillard321be0c2002-10-08 21:26:42 +00001393 xmlShellPrintNodeCtxt(NULL, node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001394}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001395#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001396
Daniel Veillard78d12092001-10-11 09:12:24 +00001397/**
Daniel Veillard321be0c2002-10-08 21:26:42 +00001398 * xmlShellPrintXPathResultCtxt:
1399 * @ctxt: a valid shell context
Daniel Veillard9d06d302002-01-22 18:15:52 +00001400 * @list: a valid result generated by an xpath evaluation
Daniel Veillard78d12092001-10-11 09:12:24 +00001401 *
Daniel Veillard321be0c2002-10-08 21:26:42 +00001402 * Prints result to the output FILE
Daniel Veillard78d12092001-10-11 09:12:24 +00001403 */
Daniel Veillard321be0c2002-10-08 21:26:42 +00001404static void
1405xmlShellPrintXPathResultCtxt(xmlShellCtxtPtr ctxt,xmlXPathObjectPtr list)
Daniel Veillard78d12092001-10-11 09:12:24 +00001406{
Daniel Veillard321be0c2002-10-08 21:26:42 +00001407 if (!ctxt)
1408 return;
Daniel Veillard78d12092001-10-11 09:12:24 +00001409
1410 if (list != NULL) {
1411 switch (list->type) {
1412 case XPATH_NODESET:{
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001413#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001414 int indx;
1415
1416 if (list->nodesetval) {
1417 for (indx = 0; indx < list->nodesetval->nodeNr;
1418 indx++) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001419 xmlShellPrintNodeCtxt(ctxt,
1420 list->nodesetval->nodeTab[indx]);
Daniel Veillard78d12092001-10-11 09:12:24 +00001421 }
1422 } else {
1423 xmlGenericError(xmlGenericErrorContext,
1424 "Empty node set\n");
1425 }
1426 break;
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001427#else
1428 xmlGenericError(xmlGenericErrorContext,
1429 "Node set\n");
1430#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001431 }
1432 case XPATH_BOOLEAN:
1433 xmlGenericError(xmlGenericErrorContext,
1434 "Is a Boolean:%s\n",
1435 xmlBoolToText(list->boolval));
1436 break;
1437 case XPATH_NUMBER:
1438 xmlGenericError(xmlGenericErrorContext,
1439 "Is a number:%0g\n", list->floatval);
1440 break;
1441 case XPATH_STRING:
1442 xmlGenericError(xmlGenericErrorContext,
1443 "Is a string:%s\n", list->stringval);
1444 break;
1445
1446 default:
1447 xmlShellPrintXPathError(list->type, NULL);
1448 }
1449 }
1450}
1451
1452/**
Daniel Veillard321be0c2002-10-08 21:26:42 +00001453 * xmlShellPrintXPathResult:
1454 * @list: a valid result generated by an xpath evaluation
1455 *
1456 * Prints result to the output FILE
1457 */
1458void
1459xmlShellPrintXPathResult(xmlXPathObjectPtr list)
1460{
1461 xmlShellPrintXPathResultCtxt(NULL, list);
1462}
1463
1464/**
Owen Taylor3473f882001-02-23 17:55:21 +00001465 * xmlShellList:
1466 * @ctxt: the shell context
1467 * @arg: unused
1468 * @node: a node
1469 * @node2: unused
1470 *
1471 * Implements the XML shell function "ls"
1472 * Does an Unix like listing of the given node (like a directory)
1473 *
1474 * Returns 0
1475 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001476int
Daniel Veillard321be0c2002-10-08 21:26:42 +00001477xmlShellList(xmlShellCtxtPtr ctxt,
Daniel Veillard78d12092001-10-11 09:12:24 +00001478 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1479 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1480{
Owen Taylor3473f882001-02-23 17:55:21 +00001481 xmlNodePtr cur;
Daniel Veillard321be0c2002-10-08 21:26:42 +00001482 if (!ctxt)
1483 return (0);
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001484 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001485 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001486 return (0);
1487 }
Owen Taylor3473f882001-02-23 17:55:21 +00001488 if ((node->type == XML_DOCUMENT_NODE) ||
1489 (node->type == XML_HTML_DOCUMENT_NODE)) {
1490 cur = ((xmlDocPtr) node)->children;
Daniel Veillarde6a55192002-01-14 17:11:53 +00001491 } else if (node->type == XML_NAMESPACE_DECL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001492 xmlLsOneNode(ctxt->output, node);
Daniel Veillarde6a55192002-01-14 17:11:53 +00001493 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001494 } else if (node->children != NULL) {
1495 cur = node->children;
1496 } else {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001497 xmlLsOneNode(ctxt->output, node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001498 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001499 }
1500 while (cur != NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001501 xmlLsOneNode(ctxt->output, cur);
Daniel Veillard78d12092001-10-11 09:12:24 +00001502 cur = cur->next;
Owen Taylor3473f882001-02-23 17:55:21 +00001503 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001504 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001505}
1506
1507/**
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001508 * xmlShellBase:
1509 * @ctxt: the shell context
1510 * @arg: unused
1511 * @node: a node
1512 * @node2: unused
1513 *
1514 * Implements the XML shell function "base"
1515 * dumps the current XML base of the node
1516 *
1517 * Returns 0
1518 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001519int
Daniel Veillard321be0c2002-10-08 21:26:42 +00001520xmlShellBase(xmlShellCtxtPtr ctxt,
Daniel Veillard78d12092001-10-11 09:12:24 +00001521 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1522 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1523{
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001524 xmlChar *base;
Daniel Veillard321be0c2002-10-08 21:26:42 +00001525 if (!ctxt)
1526 return 0;
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001527 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001528 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001529 return (0);
1530 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001531
1532 base = xmlNodeGetBase(node->doc, node);
1533
1534 if (base == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001535 fprintf(ctxt->output, " No base found !!!\n");
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001536 } else {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001537 fprintf(ctxt->output, "%s\n", base);
Daniel Veillard78d12092001-10-11 09:12:24 +00001538 xmlFree(base);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001539 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001540 return (0);
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001541}
1542
Daniel Veillardb34321c2004-03-04 17:09:47 +00001543#ifdef LIBXML_TREE_ENABLED
Daniel Veillardb8c9be92001-07-09 16:01:19 +00001544/**
Daniel Veillardcfa0d812002-01-17 08:46:58 +00001545 * xmlShellSetBase:
1546 * @ctxt: the shell context
1547 * @arg: the new base
1548 * @node: a node
1549 * @node2: unused
1550 *
1551 * Implements the XML shell function "setbase"
1552 * change the current XML base of the node
1553 *
1554 * Returns 0
1555 */
1556static int
1557xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1558 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1559 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1560{
1561 xmlNodeSetBase(node, (xmlChar*) arg);
1562 return (0);
1563}
Daniel Veillard2156d432004-03-04 15:59:36 +00001564#endif
Daniel Veillardcfa0d812002-01-17 08:46:58 +00001565
Daniel Veillardbbaa9972004-06-16 14:08:33 +00001566#ifdef LIBXML_XPATH_ENABLED
1567/**
1568 * xmlShellRegisterNamespace:
1569 * @ctxt: the shell context
1570 * @arg: a string in prefix=nsuri format
1571 * @node: unused
1572 * @node2: unused
1573 *
1574 * Implements the XML shell function "setns"
1575 * register/unregister a prefix=namespace pair
1576 * on the XPath context
1577 *
1578 * Returns 0 on success and a negative value otherwise.
1579 */
1580static int
1581xmlShellRegisterNamespace(xmlShellCtxtPtr ctxt, char *arg,
1582 xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1583{
1584 xmlChar* nsListDup;
1585 xmlChar* prefix;
1586 xmlChar* href;
1587 xmlChar* next;
1588
1589 nsListDup = xmlStrdup((xmlChar *) arg);
1590 next = nsListDup;
1591 while(next != NULL) {
1592 /* skip spaces */
1593 /*while((*next) == ' ') next++;*/
1594 if((*next) == '\0') break;
1595
1596 /* find prefix */
1597 prefix = next;
1598 next = (xmlChar*)xmlStrchr(next, '=');
1599 if(next == NULL) {
1600 fprintf(ctxt->output, "setns: prefix=[nsuri] required\n");
1601 xmlFree(nsListDup);
1602 return(-1);
1603 }
1604 *(next++) = '\0';
1605
1606 /* find href */
1607 href = next;
1608 next = (xmlChar*)xmlStrchr(next, ' ');
1609 if(next != NULL) {
1610 *(next++) = '\0';
1611 }
1612
1613 /* do register namespace */
1614 if(xmlXPathRegisterNs(ctxt->pctxt, prefix, href) != 0) {
1615 fprintf(ctxt->output,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", prefix, href);
1616 xmlFree(nsListDup);
1617 return(-1);
1618 }
1619 }
1620
1621 xmlFree(nsListDup);
1622 return(0);
1623}
1624#endif
1625
Daniel Veillardcfa0d812002-01-17 08:46:58 +00001626/**
Daniel Veillard1e208222002-10-22 14:25:25 +00001627 * xmlShellGrep:
1628 * @ctxt: the shell context
1629 * @arg: the string or regular expression to find
1630 * @node: a node
1631 * @node2: unused
1632 *
1633 * Implements the XML shell function "grep"
1634 * dumps informations about the node (namespace, attributes, content).
1635 *
1636 * Returns 0
1637 */
Daniel Veillarde645e8c2002-10-22 17:35:37 +00001638static int
Daniel Veillard1e208222002-10-22 14:25:25 +00001639xmlShellGrep(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1640 char *arg, xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1641{
1642 if (!ctxt)
1643 return (0);
1644 if (node == NULL)
1645 return (0);
1646 if (arg == NULL)
1647 return (0);
1648#ifdef LIBXML_REGEXP_ENABLED
1649 if ((xmlStrchr((xmlChar *) arg, '?')) ||
1650 (xmlStrchr((xmlChar *) arg, '*')) ||
1651 (xmlStrchr((xmlChar *) arg, '.')) ||
1652 (xmlStrchr((xmlChar *) arg, '['))) {
1653 }
1654#endif
1655 while (node != NULL) {
1656 if (node->type == XML_COMMENT_NODE) {
Daniel Veillarde645e8c2002-10-22 17:35:37 +00001657 if (xmlStrstr(node->content, (xmlChar *) arg)) {
Daniel Veillard1e208222002-10-22 14:25:25 +00001658
1659 fprintf(ctxt->output, "%s : ", xmlGetNodePath(node));
1660 xmlShellList(ctxt, NULL, node, NULL);
1661 }
1662 } else if (node->type == XML_TEXT_NODE) {
Daniel Veillarde645e8c2002-10-22 17:35:37 +00001663 if (xmlStrstr(node->content, (xmlChar *) arg)) {
Daniel Veillard1e208222002-10-22 14:25:25 +00001664
1665 fprintf(ctxt->output, "%s : ", xmlGetNodePath(node->parent));
Daniel Veillarde645e8c2002-10-22 17:35:37 +00001666 xmlShellList(ctxt, NULL, node->parent, NULL);
Daniel Veillard1e208222002-10-22 14:25:25 +00001667 }
1668 }
1669
1670 /*
1671 * Browse the full subtree, deep first
1672 */
1673
1674 if ((node->type == XML_DOCUMENT_NODE) ||
1675 (node->type == XML_HTML_DOCUMENT_NODE)) {
1676 node = ((xmlDocPtr) node)->children;
1677 } else if ((node->children != NULL)
1678 && (node->type != XML_ENTITY_REF_NODE)) {
1679 /* deep first */
1680 node = node->children;
1681 } else if (node->next != NULL) {
1682 /* then siblings */
1683 node = node->next;
1684 } else {
1685 /* go up to parents->next if needed */
1686 while (node != NULL) {
1687 if (node->parent != NULL) {
1688 node = node->parent;
1689 }
1690 if (node->next != NULL) {
1691 node = node->next;
1692 break;
1693 }
1694 if (node->parent == NULL) {
1695 node = NULL;
1696 break;
1697 }
1698 }
1699 }
1700 }
1701 return (0);
1702}
1703
1704/**
Owen Taylor3473f882001-02-23 17:55:21 +00001705 * xmlShellDir:
1706 * @ctxt: the shell context
1707 * @arg: unused
1708 * @node: a node
1709 * @node2: unused
1710 *
1711 * Implements the XML shell function "dir"
1712 * dumps informations about the node (namespace, attributes, content).
1713 *
1714 * Returns 0
1715 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001716int
1717xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1718 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1719 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1720{
Daniel Veillard321be0c2002-10-08 21:26:42 +00001721 if (!ctxt)
1722 return (0);
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001723 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001724 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001725 return (0);
1726 }
Owen Taylor3473f882001-02-23 17:55:21 +00001727 if ((node->type == XML_DOCUMENT_NODE) ||
1728 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001729 xmlDebugDumpDocumentHead(ctxt->output, (xmlDocPtr) node);
Owen Taylor3473f882001-02-23 17:55:21 +00001730 } else if (node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001731 xmlDebugDumpAttr(ctxt->output, (xmlAttrPtr) node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00001732 } else {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001733 xmlDebugDumpOneNode(ctxt->output, node, 0);
Owen Taylor3473f882001-02-23 17:55:21 +00001734 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001735 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001736}
1737
Daniel Veillard29b17482004-08-16 00:39:03 +00001738/**
1739 * xmlShellSetContent:
1740 * @ctxt: the shell context
1741 * @value: the content as a string
1742 * @node: a node
1743 * @node2: unused
1744 *
1745 * Implements the XML shell function "dir"
1746 * dumps informations about the node (namespace, attributes, content).
1747 *
1748 * Returns 0
1749 */
1750static int
1751xmlShellSetContent(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1752 char *value, xmlNodePtr node,
1753 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1754{
1755 xmlNodePtr results;
1756 xmlParserErrors ret;
1757
1758 if (!ctxt)
1759 return (0);
1760 if (node == NULL) {
1761 fprintf(ctxt->output, "NULL\n");
1762 return (0);
1763 }
1764 if (value == NULL) {
1765 fprintf(ctxt->output, "NULL\n");
1766 return (0);
1767 }
1768
1769 ret = xmlParseInNodeContext(node, value, strlen(value), 0, &results);
1770 if (ret == XML_ERR_OK) {
1771 if (node->children != NULL) {
1772 xmlFreeNodeList(node->children);
1773 node->children = NULL;
1774 node->last = NULL;
1775 }
1776 xmlAddChildList(node, results);
1777 } else {
1778 fprintf(ctxt->output, "failed to parse content\n");
1779 }
1780 return (0);
1781}
1782
Daniel Veillard522bc602004-02-21 11:53:09 +00001783#ifdef LIBXML_SCHEMAS_ENABLED
1784/**
1785 * xmlShellRNGValidate:
1786 * @ctxt: the shell context
1787 * @schemas: the path to the Relax-NG schemas
1788 * @node: a node
1789 * @node2: unused
1790 *
1791 * Implements the XML shell function "relaxng"
1792 * validating the instance against a Relax-NG schemas
1793 *
1794 * Returns 0
1795 */
1796static int
1797xmlShellRNGValidate(xmlShellCtxtPtr sctxt, char *schemas,
1798 xmlNodePtr node ATTRIBUTE_UNUSED,
1799 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1800{
1801 xmlRelaxNGPtr relaxngschemas;
1802 xmlRelaxNGParserCtxtPtr ctxt;
1803 xmlRelaxNGValidCtxtPtr vctxt;
1804 int ret;
1805
1806 ctxt = xmlRelaxNGNewParserCtxt(schemas);
1807 xmlRelaxNGSetParserErrors(ctxt,
1808 (xmlRelaxNGValidityErrorFunc) fprintf,
1809 (xmlRelaxNGValidityWarningFunc) fprintf,
1810 stderr);
1811 relaxngschemas = xmlRelaxNGParse(ctxt);
1812 xmlRelaxNGFreeParserCtxt(ctxt);
1813 if (relaxngschemas == NULL) {
1814 xmlGenericError(xmlGenericErrorContext,
1815 "Relax-NG schema %s failed to compile\n", schemas);
1816 return(-1);
1817 }
1818 vctxt = xmlRelaxNGNewValidCtxt(relaxngschemas);
1819 xmlRelaxNGSetValidErrors(vctxt,
1820 (xmlRelaxNGValidityErrorFunc) fprintf,
1821 (xmlRelaxNGValidityWarningFunc) fprintf,
1822 stderr);
1823 ret = xmlRelaxNGValidateDoc(vctxt, sctxt->doc);
1824 if (ret == 0) {
1825 fprintf(stderr, "%s validates\n", sctxt->filename);
1826 } else if (ret > 0) {
1827 fprintf(stderr, "%s fails to validate\n", sctxt->filename);
1828 } else {
1829 fprintf(stderr, "%s validation generated an internal error\n",
1830 sctxt->filename);
1831 }
1832 xmlRelaxNGFreeValidCtxt(vctxt);
1833 if (relaxngschemas != NULL)
1834 xmlRelaxNGFree(relaxngschemas);
1835 return(0);
1836}
1837#endif
1838
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001839#ifdef LIBXML_OUTPUT_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00001840/**
1841 * xmlShellCat:
1842 * @ctxt: the shell context
1843 * @arg: unused
1844 * @node: a node
1845 * @node2: unused
1846 *
1847 * Implements the XML shell function "cat"
1848 * dumps the serialization node content (XML or HTML).
1849 *
1850 * Returns 0
1851 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001852int
1853xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
1854 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1855{
Daniel Veillard321be0c2002-10-08 21:26:42 +00001856 if (!ctxt)
1857 return (0);
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001858 if (node == NULL) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00001859 fprintf(ctxt->output, "NULL\n");
Daniel Veillard5e926fa2002-01-22 21:44:25 +00001860 return (0);
1861 }
Owen Taylor3473f882001-02-23 17:55:21 +00001862 if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
1863#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001864 if (node->type == XML_HTML_DOCUMENT_NODE)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001865 htmlDocDump(ctxt->output, (htmlDocPtr) node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001866 else
Daniel Veillard321be0c2002-10-08 21:26:42 +00001867 htmlNodeDumpFile(ctxt->output, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001868#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001869 if (node->type == XML_DOCUMENT_NODE)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001870 xmlDocDump(ctxt->output, (xmlDocPtr) node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001871 else
Daniel Veillard321be0c2002-10-08 21:26:42 +00001872 xmlElemDump(ctxt->output, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001873#endif /* LIBXML_HTML_ENABLED */
1874 } else {
Daniel Veillard78d12092001-10-11 09:12:24 +00001875 if (node->type == XML_DOCUMENT_NODE)
Daniel Veillard321be0c2002-10-08 21:26:42 +00001876 xmlDocDump(ctxt->output, (xmlDocPtr) node);
Daniel Veillard78d12092001-10-11 09:12:24 +00001877 else
Daniel Veillard321be0c2002-10-08 21:26:42 +00001878 xmlElemDump(ctxt->output, ctxt->doc, node);
Owen Taylor3473f882001-02-23 17:55:21 +00001879 }
Daniel Veillard321be0c2002-10-08 21:26:42 +00001880 fprintf(ctxt->output, "\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001881 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001882}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001883#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00001884
1885/**
1886 * xmlShellLoad:
1887 * @ctxt: the shell context
1888 * @filename: the file name
1889 * @node: unused
1890 * @node2: unused
1891 *
1892 * Implements the XML shell function "load"
1893 * loads a new document specified by the filename
1894 *
1895 * Returns 0 or -1 if loading failed
1896 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001897int
1898xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename,
1899 xmlNodePtr node ATTRIBUTE_UNUSED,
1900 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1901{
Owen Taylor3473f882001-02-23 17:55:21 +00001902 xmlDocPtr doc;
1903 int html = 0;
1904
1905 if (ctxt->doc != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001906 html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
Owen Taylor3473f882001-02-23 17:55:21 +00001907
1908 if (html) {
1909#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001910 doc = htmlParseFile(filename, NULL);
1911#else
Daniel Veillard321be0c2002-10-08 21:26:42 +00001912 fprintf(ctxt->output, "HTML support not compiled in\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00001913 doc = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00001914#endif /* LIBXML_HTML_ENABLED */
1915 } else {
Daniel Veillardebe25d42004-03-25 09:35:49 +00001916 doc = xmlReadFile(filename,NULL,0);
Owen Taylor3473f882001-02-23 17:55:21 +00001917 }
1918 if (doc != NULL) {
1919 if (ctxt->loaded == 1) {
Daniel Veillard78d12092001-10-11 09:12:24 +00001920 xmlFreeDoc(ctxt->doc);
1921 }
1922 ctxt->loaded = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00001923#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001924 xmlXPathFreeContext(ctxt->pctxt);
Owen Taylor3473f882001-02-23 17:55:21 +00001925#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001926 xmlFree(ctxt->filename);
1927 ctxt->doc = doc;
1928 ctxt->node = (xmlNodePtr) doc;
Owen Taylor3473f882001-02-23 17:55:21 +00001929#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001930 ctxt->pctxt = xmlXPathNewContext(doc);
Owen Taylor3473f882001-02-23 17:55:21 +00001931#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard85095e22003-04-23 13:56:44 +00001932 ctxt->filename = (char *) xmlCanonicPath((xmlChar *) filename);
Owen Taylor3473f882001-02-23 17:55:21 +00001933 } else
Daniel Veillard78d12092001-10-11 09:12:24 +00001934 return (-1);
1935 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00001936}
1937
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001938#ifdef LIBXML_OUTPUT_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00001939/**
1940 * xmlShellWrite:
1941 * @ctxt: the shell context
1942 * @filename: the file name
1943 * @node: a node in the tree
1944 * @node2: unused
1945 *
1946 * Implements the XML shell function "write"
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001947 * Write the current node to the filename, it saves the serialization
Owen Taylor3473f882001-02-23 17:55:21 +00001948 * of the subtree under the @node specified
1949 *
1950 * Returns 0 or -1 in case of error
1951 */
Daniel Veillard78d12092001-10-11 09:12:24 +00001952int
Owen Taylor3473f882001-02-23 17:55:21 +00001953xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
Daniel Veillard78d12092001-10-11 09:12:24 +00001954 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1955{
Owen Taylor3473f882001-02-23 17:55:21 +00001956 if (node == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00001957 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001958 if ((filename == NULL) || (filename[0] == 0)) {
1959 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001960 "Write command requires a filename argument\n");
1961 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001962 }
1963#ifdef W_OK
1964 if (access((char *) filename, W_OK)) {
1965 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00001966 "Cannot write to %s\n", filename);
1967 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001968 }
Daniel Veillard78d12092001-10-11 09:12:24 +00001969#endif
1970 switch (node->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00001971 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00001972 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1973 xmlGenericError(xmlGenericErrorContext,
1974 "Failed to write to %s\n", filename);
1975 return (-1);
1976 }
1977 break;
Owen Taylor3473f882001-02-23 17:55:21 +00001978 case XML_HTML_DOCUMENT_NODE:
1979#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00001980 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1981 xmlGenericError(xmlGenericErrorContext,
1982 "Failed to write to %s\n", filename);
1983 return (-1);
1984 }
Owen Taylor3473f882001-02-23 17:55:21 +00001985#else
Daniel Veillard78d12092001-10-11 09:12:24 +00001986 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1987 xmlGenericError(xmlGenericErrorContext,
1988 "Failed to write to %s\n", filename);
1989 return (-1);
1990 }
Owen Taylor3473f882001-02-23 17:55:21 +00001991#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00001992 break;
1993 default:{
1994 FILE *f;
Owen Taylor3473f882001-02-23 17:55:21 +00001995
Daniel Veillard78d12092001-10-11 09:12:24 +00001996 f = fopen((char *) filename, "w");
1997 if (f == NULL) {
1998 xmlGenericError(xmlGenericErrorContext,
1999 "Failed to write to %s\n", filename);
2000 return (-1);
2001 }
2002 xmlElemDump(f, ctxt->doc, node);
2003 fclose(f);
2004 }
Owen Taylor3473f882001-02-23 17:55:21 +00002005 }
Daniel Veillard78d12092001-10-11 09:12:24 +00002006 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002007}
2008
2009/**
2010 * xmlShellSave:
2011 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00002012 * @filename: the file name (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00002013 * @node: unused
2014 * @node2: unused
2015 *
2016 * Implements the XML shell function "save"
2017 * Write the current document to the filename, or it's original name
2018 *
2019 * Returns 0 or -1 in case of error
2020 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002021int
2022xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
2023 xmlNodePtr node ATTRIBUTE_UNUSED,
2024 xmlNodePtr node2 ATTRIBUTE_UNUSED)
2025{
Owen Taylor3473f882001-02-23 17:55:21 +00002026 if (ctxt->doc == NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002027 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002028 if ((filename == NULL) || (filename[0] == 0))
2029 filename = ctxt->filename;
2030#ifdef W_OK
2031 if (access((char *) filename, W_OK)) {
2032 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard78d12092001-10-11 09:12:24 +00002033 "Cannot save to %s\n", filename);
2034 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002035 }
2036#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00002037 switch (ctxt->doc->type) {
Owen Taylor3473f882001-02-23 17:55:21 +00002038 case XML_DOCUMENT_NODE:
Daniel Veillard78d12092001-10-11 09:12:24 +00002039 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
2040 xmlGenericError(xmlGenericErrorContext,
2041 "Failed to save to %s\n", filename);
2042 }
2043 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002044 case XML_HTML_DOCUMENT_NODE:
2045#ifdef LIBXML_HTML_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002046 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
2047 xmlGenericError(xmlGenericErrorContext,
2048 "Failed to save to %s\n", filename);
2049 }
Owen Taylor3473f882001-02-23 17:55:21 +00002050#else
Daniel Veillard78d12092001-10-11 09:12:24 +00002051 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
2052 xmlGenericError(xmlGenericErrorContext,
2053 "Failed to save to %s\n", filename);
2054 }
Owen Taylor3473f882001-02-23 17:55:21 +00002055#endif /* LIBXML_HTML_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00002056 break;
2057 default:
2058 xmlGenericError(xmlGenericErrorContext,
2059 "To save to subparts of a document use the 'write' command\n");
2060 return (-1);
2061
Owen Taylor3473f882001-02-23 17:55:21 +00002062 }
Daniel Veillard78d12092001-10-11 09:12:24 +00002063 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002064}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002065#endif /* LIBXML_OUTPUT_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00002066
Daniel Veillardf54cd532004-02-25 11:52:31 +00002067#ifdef LIBXML_VALID_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00002068/**
2069 * xmlShellValidate:
2070 * @ctxt: the shell context
Daniel Veillardcbaf3992001-12-31 16:16:02 +00002071 * @dtd: the DTD URI (optional)
Owen Taylor3473f882001-02-23 17:55:21 +00002072 * @node: unused
2073 * @node2: unused
2074 *
2075 * Implements the XML shell function "validate"
2076 * Validate the document, if a DTD path is provided, then the validation
2077 * is done against the given DTD.
2078 *
2079 * Returns 0 or -1 in case of error
2080 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002081int
2082xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd,
2083 xmlNodePtr node ATTRIBUTE_UNUSED,
2084 xmlNodePtr node2 ATTRIBUTE_UNUSED)
2085{
Owen Taylor3473f882001-02-23 17:55:21 +00002086 xmlValidCtxt vctxt;
2087 int res = -1;
2088
2089 vctxt.userData = stderr;
2090 vctxt.error = (xmlValidityErrorFunc) fprintf;
2091 vctxt.warning = (xmlValidityWarningFunc) fprintf;
2092
2093 if ((dtd == NULL) || (dtd[0] == 0)) {
2094 res = xmlValidateDocument(&vctxt, ctxt->doc);
2095 } else {
2096 xmlDtdPtr subset;
2097
Daniel Veillard78d12092001-10-11 09:12:24 +00002098 subset = xmlParseDTD(NULL, (xmlChar *) dtd);
2099 if (subset != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00002100 res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
2101
Daniel Veillard78d12092001-10-11 09:12:24 +00002102 xmlFreeDtd(subset);
2103 }
Owen Taylor3473f882001-02-23 17:55:21 +00002104 }
Daniel Veillard78d12092001-10-11 09:12:24 +00002105 return (res);
Owen Taylor3473f882001-02-23 17:55:21 +00002106}
Daniel Veillardf54cd532004-02-25 11:52:31 +00002107#endif /* LIBXML_VALID_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00002108
2109/**
2110 * xmlShellDu:
2111 * @ctxt: the shell context
2112 * @arg: unused
2113 * @tree: a node defining a subtree
2114 * @node2: unused
2115 *
2116 * Implements the XML shell function "du"
2117 * show the structure of the subtree under node @tree
2118 * If @tree is null, the command works on the current node.
2119 *
2120 * Returns 0 or -1 in case of error
2121 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002122int
Daniel Veillard321be0c2002-10-08 21:26:42 +00002123xmlShellDu(xmlShellCtxtPtr ctxt,
Daniel Veillard78d12092001-10-11 09:12:24 +00002124 char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree,
2125 xmlNodePtr node2 ATTRIBUTE_UNUSED)
2126{
Owen Taylor3473f882001-02-23 17:55:21 +00002127 xmlNodePtr node;
Daniel Veillard78d12092001-10-11 09:12:24 +00002128 int indent = 0, i;
Owen Taylor3473f882001-02-23 17:55:21 +00002129
Daniel Veillard321be0c2002-10-08 21:26:42 +00002130 if (!ctxt)
2131 return (-1);
2132
Daniel Veillard78d12092001-10-11 09:12:24 +00002133 if (tree == NULL)
2134 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002135 node = tree;
2136 while (node != NULL) {
2137 if ((node->type == XML_DOCUMENT_NODE) ||
2138 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002139 fprintf(ctxt->output, "/\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00002140 } else if (node->type == XML_ELEMENT_NODE) {
2141 for (i = 0; i < indent; i++)
Daniel Veillard321be0c2002-10-08 21:26:42 +00002142 fprintf(ctxt->output, " ");
2143 fprintf(ctxt->output, "%s\n", node->name);
Daniel Veillard78d12092001-10-11 09:12:24 +00002144 } else {
2145 }
Owen Taylor3473f882001-02-23 17:55:21 +00002146
Daniel Veillard78d12092001-10-11 09:12:24 +00002147 /*
2148 * Browse the full subtree, deep first
2149 */
Owen Taylor3473f882001-02-23 17:55:21 +00002150
2151 if ((node->type == XML_DOCUMENT_NODE) ||
2152 (node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002153 node = ((xmlDocPtr) node)->children;
2154 } else if ((node->children != NULL)
2155 && (node->type != XML_ENTITY_REF_NODE)) {
2156 /* deep first */
2157 node = node->children;
2158 indent++;
2159 } else if ((node != tree) && (node->next != NULL)) {
2160 /* then siblings */
2161 node = node->next;
2162 } else if (node != tree) {
2163 /* go up to parents->next if needed */
2164 while (node != tree) {
2165 if (node->parent != NULL) {
2166 node = node->parent;
2167 indent--;
2168 }
2169 if ((node != tree) && (node->next != NULL)) {
2170 node = node->next;
2171 break;
2172 }
2173 if (node->parent == NULL) {
2174 node = NULL;
2175 break;
2176 }
2177 if (node == tree) {
2178 node = NULL;
2179 break;
2180 }
2181 }
2182 /* exit condition */
2183 if (node == tree)
2184 node = NULL;
2185 } else
2186 node = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00002187 }
Daniel Veillard78d12092001-10-11 09:12:24 +00002188 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002189}
2190
2191/**
2192 * xmlShellPwd:
2193 * @ctxt: the shell context
2194 * @buffer: the output buffer
Daniel Veillard9d06d302002-01-22 18:15:52 +00002195 * @node: a node
Owen Taylor3473f882001-02-23 17:55:21 +00002196 * @node2: unused
2197 *
2198 * Implements the XML shell function "pwd"
2199 * Show the full path from the root to the node, if needed building
2200 * thumblers when similar elements exists at a given ancestor level.
2201 * The output is compatible with XPath commands.
2202 *
2203 * Returns 0 or -1 in case of error
2204 */
Daniel Veillard78d12092001-10-11 09:12:24 +00002205int
2206xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
2207 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2208{
Daniel Veillardc6e013a2001-11-10 10:08:57 +00002209 xmlChar *path;
Owen Taylor3473f882001-02-23 17:55:21 +00002210
Daniel Veillard78d12092001-10-11 09:12:24 +00002211 if (node == NULL)
2212 return (-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002213
Daniel Veillardc6e013a2001-11-10 10:08:57 +00002214 path = xmlGetNodePath(node);
2215 if (path == NULL)
2216 return (-1);
2217
2218 /*
2219 * This test prevents buffer overflow, because this routine
2220 * is only called by xmlShell, in which the second argument is
2221 * 500 chars long.
2222 * It is a dirty hack before a cleaner solution is found.
2223 * Documentation should mention that the second argument must
2224 * be at least 500 chars long, and could be stripped if too long.
2225 */
2226 snprintf(buffer, 499, "%s", path);
2227 buffer[499] = '0';
2228 xmlFree(path);
2229
Daniel Veillard78d12092001-10-11 09:12:24 +00002230 return (0);
Owen Taylor3473f882001-02-23 17:55:21 +00002231}
2232
2233/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002234 * xmlShell:
Owen Taylor3473f882001-02-23 17:55:21 +00002235 * @doc: the initial document
2236 * @filename: the output buffer
2237 * @input: the line reading function
Daniel Veillard321be0c2002-10-08 21:26:42 +00002238 * @output: the output FILE*, defaults to stdout if NULL
Owen Taylor3473f882001-02-23 17:55:21 +00002239 *
2240 * Implements the XML shell
2241 * This allow to load, validate, view, modify and save a document
2242 * using a environment similar to a UNIX commandline.
2243 */
2244void
2245xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
Daniel Veillard78d12092001-10-11 09:12:24 +00002246 FILE * output)
2247{
Owen Taylor3473f882001-02-23 17:55:21 +00002248 char prompt[500] = "/ > ";
2249 char *cmdline = NULL, *cur;
2250 int nbargs;
2251 char command[100];
2252 char arg[400];
2253 int i;
2254 xmlShellCtxtPtr ctxt;
2255 xmlXPathObjectPtr list;
2256
2257 if (doc == NULL)
2258 return;
2259 if (filename == NULL)
2260 return;
2261 if (input == NULL)
2262 return;
2263 if (output == NULL)
Daniel Veillard321be0c2002-10-08 21:26:42 +00002264 output = stdout;
Owen Taylor3473f882001-02-23 17:55:21 +00002265 ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
Daniel Veillard78d12092001-10-11 09:12:24 +00002266 if (ctxt == NULL)
Owen Taylor3473f882001-02-23 17:55:21 +00002267 return;
2268 ctxt->loaded = 0;
2269 ctxt->doc = doc;
2270 ctxt->input = input;
2271 ctxt->output = output;
2272 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
Daniel Veillard78d12092001-10-11 09:12:24 +00002273 ctxt->node = (xmlNodePtr) ctxt->doc;
Owen Taylor3473f882001-02-23 17:55:21 +00002274
2275#ifdef LIBXML_XPATH_ENABLED
2276 ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
2277 if (ctxt->pctxt == NULL) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002278 xmlFree(ctxt);
2279 return;
Owen Taylor3473f882001-02-23 17:55:21 +00002280 }
2281#endif /* LIBXML_XPATH_ENABLED */
2282 while (1) {
2283 if (ctxt->node == (xmlNodePtr) ctxt->doc)
Aleksey Sanin49cc9752002-06-14 17:07:10 +00002284 snprintf(prompt, sizeof(prompt), "%s > ", "/");
Daniel Veillard7a985a12003-07-06 17:57:42 +00002285 else if ((ctxt->node != NULL) && (ctxt->node->name))
Daniel Veillard78d12092001-10-11 09:12:24 +00002286 snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
Owen Taylor3473f882001-02-23 17:55:21 +00002287 else
Aleksey Sanin49cc9752002-06-14 17:07:10 +00002288 snprintf(prompt, sizeof(prompt), "? > ");
Owen Taylor3473f882001-02-23 17:55:21 +00002289 prompt[sizeof(prompt) - 1] = 0;
2290
Daniel Veillard78d12092001-10-11 09:12:24 +00002291 /*
2292 * Get a new command line
2293 */
Owen Taylor3473f882001-02-23 17:55:21 +00002294 cmdline = ctxt->input(prompt);
Daniel Veillard78d12092001-10-11 09:12:24 +00002295 if (cmdline == NULL)
2296 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002297
Daniel Veillard78d12092001-10-11 09:12:24 +00002298 /*
2299 * Parse the command itself
2300 */
2301 cur = cmdline;
2302 nbargs = 0;
2303 while ((*cur == ' ') || (*cur == '\t'))
2304 cur++;
2305 i = 0;
2306 while ((*cur != ' ') && (*cur != '\t') &&
2307 (*cur != '\n') && (*cur != '\r')) {
2308 if (*cur == 0)
2309 break;
2310 command[i++] = *cur++;
2311 }
2312 command[i] = 0;
2313 if (i == 0)
2314 continue;
2315 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00002316
Daniel Veillard78d12092001-10-11 09:12:24 +00002317 /*
2318 * Parse the argument
2319 */
2320 while ((*cur == ' ') || (*cur == '\t'))
2321 cur++;
2322 i = 0;
2323 while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
2324 if (*cur == 0)
2325 break;
2326 arg[i++] = *cur++;
2327 }
2328 arg[i] = 0;
2329 if (i != 0)
2330 nbargs++;
Owen Taylor3473f882001-02-23 17:55:21 +00002331
Daniel Veillard78d12092001-10-11 09:12:24 +00002332 /*
2333 * start interpreting the command
2334 */
Owen Taylor3473f882001-02-23 17:55:21 +00002335 if (!strcmp(command, "exit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002336 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002337 if (!strcmp(command, "quit"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002338 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002339 if (!strcmp(command, "bye"))
Daniel Veillard78d12092001-10-11 09:12:24 +00002340 break;
Daniel Veillard5004f422001-11-08 13:53:05 +00002341 if (!strcmp(command, "help")) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002342 fprintf(ctxt->output, "\tbase display XML base of the node\n");
2343 fprintf(ctxt->output, "\tsetbase URI change the XML base of the node\n");
2344 fprintf(ctxt->output, "\tbye leave shell\n");
2345 fprintf(ctxt->output, "\tcat [node] display node or current node\n");
2346 fprintf(ctxt->output, "\tcd [path] change directory to path or to root\n");
2347 fprintf(ctxt->output, "\tdir [path] dumps informations about the node (namespace, attributes, content)\n");
2348 fprintf(ctxt->output, "\tdu [path] show the structure of the subtree under path or the current node\n");
2349 fprintf(ctxt->output, "\texit leave shell\n");
2350 fprintf(ctxt->output, "\thelp display this help\n");
2351 fprintf(ctxt->output, "\tfree display memory usage\n");
2352 fprintf(ctxt->output, "\tload [name] load a new document with name\n");
2353 fprintf(ctxt->output, "\tls [path] list contents of path or the current directory\n");
Daniel Veillardc14c3892004-08-16 12:34:50 +00002354 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 +00002355#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard321be0c2002-10-08 21:26:42 +00002356 fprintf(ctxt->output, "\txpath expr evaluate the XPath expression in that context and print the result\n");
Daniel Veillardbbaa9972004-06-16 14:08:33 +00002357 fprintf(ctxt->output, "\tsetns nsreg register a namespace to a prefix in the XPath evaluation context\n");
2358 fprintf(ctxt->output, "\t format for nsreg is: prefix=[nsuri] (i.e. prefix= unsets a prefix)\n");
Daniel Veillard2070c482002-01-22 22:12:19 +00002359#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard321be0c2002-10-08 21:26:42 +00002360 fprintf(ctxt->output, "\tpwd display current working directory\n");
2361 fprintf(ctxt->output, "\tquit leave shell\n");
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002362#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard321be0c2002-10-08 21:26:42 +00002363 fprintf(ctxt->output, "\tsave [name] save this document to name or the original name\n");
Daniel Veillard321be0c2002-10-08 21:26:42 +00002364 fprintf(ctxt->output, "\twrite [name] write the current node to the filename\n");
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002365#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillardf54cd532004-02-25 11:52:31 +00002366#ifdef LIBXML_VALID_ENABLED
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002367 fprintf(ctxt->output, "\tvalidate check the document for errors\n");
Daniel Veillardf54cd532004-02-25 11:52:31 +00002368#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard522bc602004-02-21 11:53:09 +00002369#ifdef LIBXML_SCHEMAS_ENABLED
2370 fprintf(ctxt->output, "\trelaxng rng validate the document agaisnt the Relax-NG schemas\n");
2371#endif
Daniel Veillard1e208222002-10-22 14:25:25 +00002372 fprintf(ctxt->output, "\tgrep string search for a string in the subtree\n");
Daniel Veillardf54cd532004-02-25 11:52:31 +00002373#ifdef LIBXML_VALID_ENABLED
Daniel Veillard5004f422001-11-08 13:53:05 +00002374 } else if (!strcmp(command, "validate")) {
Daniel Veillard78d12092001-10-11 09:12:24 +00002375 xmlShellValidate(ctxt, arg, NULL, NULL);
Daniel Veillardf54cd532004-02-25 11:52:31 +00002376#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00002377 } else if (!strcmp(command, "load")) {
2378 xmlShellLoad(ctxt, arg, NULL, NULL);
Daniel Veillard522bc602004-02-21 11:53:09 +00002379#ifdef LIBXML_SCHEMAS_ENABLED
2380 } else if (!strcmp(command, "relaxng")) {
2381 xmlShellRNGValidate(ctxt, arg, NULL, NULL);
2382#endif
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002383#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002384 } else if (!strcmp(command, "save")) {
2385 xmlShellSave(ctxt, arg, NULL, NULL);
2386 } else if (!strcmp(command, "write")) {
2387 xmlShellWrite(ctxt, arg, NULL, NULL);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002388#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard1e208222002-10-22 14:25:25 +00002389 } else if (!strcmp(command, "grep")) {
2390 xmlShellGrep(ctxt, arg, ctxt->node, NULL);
Daniel Veillard78d12092001-10-11 09:12:24 +00002391 } else if (!strcmp(command, "free")) {
2392 if (arg[0] == 0) {
Daniel Veillard321be0c2002-10-08 21:26:42 +00002393 xmlMemShow(ctxt->output, 0);
Daniel Veillard78d12092001-10-11 09:12:24 +00002394 } else {
2395 int len = 0;
Owen Taylor3473f882001-02-23 17:55:21 +00002396
Daniel Veillard78d12092001-10-11 09:12:24 +00002397 sscanf(arg, "%d", &len);
Daniel Veillard321be0c2002-10-08 21:26:42 +00002398 xmlMemShow(ctxt->output, len);
Daniel Veillard78d12092001-10-11 09:12:24 +00002399 }
2400 } else if (!strcmp(command, "pwd")) {
2401 char dir[500];
Owen Taylor3473f882001-02-23 17:55:21 +00002402
Daniel Veillard78d12092001-10-11 09:12:24 +00002403 if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
Daniel Veillard321be0c2002-10-08 21:26:42 +00002404 fprintf(ctxt->output, "%s\n", dir);
Daniel Veillard78d12092001-10-11 09:12:24 +00002405 } else if (!strcmp(command, "du")) {
2406 xmlShellDu(ctxt, NULL, ctxt->node, NULL);
2407 } else if (!strcmp(command, "base")) {
2408 xmlShellBase(ctxt, NULL, ctxt->node, NULL);
Daniel Veillard29b17482004-08-16 00:39:03 +00002409 } else if (!strcmp(command, "set")) {
2410 xmlShellSetContent(ctxt, arg, ctxt->node, NULL);
Daniel Veillard2070c482002-01-22 22:12:19 +00002411#ifdef LIBXML_XPATH_ENABLED
Daniel Veillardbbaa9972004-06-16 14:08:33 +00002412 } else if (!strcmp(command, "setns")) {
2413 if (arg[0] == 0) {
2414 xmlGenericError(xmlGenericErrorContext,
2415 "setns: prefix=[nsuri] required\n");
2416 } else {
2417 xmlShellRegisterNamespace(ctxt, arg, NULL, NULL);
2418 }
Daniel Veillard2070c482002-01-22 22:12:19 +00002419 } else if (!strcmp(command, "xpath")) {
2420 if (arg[0] == 0) {
2421 xmlGenericError(xmlGenericErrorContext,
2422 "xpath: expression required\n");
2423 } else {
2424 ctxt->pctxt->node = ctxt->node;
2425 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
Daniel Veillard321be0c2002-10-08 21:26:42 +00002426 xmlXPathDebugDumpObject(ctxt->output, list, 0);
Daniel Veillard2070c482002-01-22 22:12:19 +00002427 xmlXPathFreeObject(list);
2428 }
2429#endif /* LIBXML_XPATH_ENABLED */
Daniel Veillard2156d432004-03-04 15:59:36 +00002430#ifdef LIBXML_TREE_ENABLED
Daniel Veillardcfa0d812002-01-17 08:46:58 +00002431 } else if (!strcmp(command, "setbase")) {
2432 xmlShellSetBase(ctxt, arg, ctxt->node, NULL);
Daniel Veillard2156d432004-03-04 15:59:36 +00002433#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00002434 } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) {
2435 int dir = (!strcmp(command, "dir"));
2436
2437 if (arg[0] == 0) {
2438 if (dir)
2439 xmlShellDir(ctxt, NULL, ctxt->node, NULL);
2440 else
2441 xmlShellList(ctxt, NULL, ctxt->node, NULL);
2442 } else {
2443 ctxt->pctxt->node = ctxt->node;
Daniel Veillard61d80a22001-04-27 17:13:01 +00002444#ifdef LIBXML_XPATH_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002445 ctxt->pctxt->node = ctxt->node;
2446 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2447#else
2448 list = NULL;
2449#endif /* LIBXML_XPATH_ENABLED */
2450 if (list != NULL) {
2451 switch (list->type) {
2452 case XPATH_UNDEFINED:
2453 xmlGenericError(xmlGenericErrorContext,
2454 "%s: no such node\n", arg);
2455 break;
2456 case XPATH_NODESET:{
2457 int indx;
2458
Daniel Veillarda6825e82001-11-07 13:33:59 +00002459 if (list->nodesetval == NULL)
2460 break;
2461
Daniel Veillard78d12092001-10-11 09:12:24 +00002462 for (indx = 0;
2463 indx < list->nodesetval->nodeNr;
2464 indx++) {
2465 if (dir)
2466 xmlShellDir(ctxt, NULL,
2467 list->nodesetval->
2468 nodeTab[indx], NULL);
2469 else
2470 xmlShellList(ctxt, NULL,
2471 list->nodesetval->
2472 nodeTab[indx], NULL);
2473 }
2474 break;
2475 }
2476 case XPATH_BOOLEAN:
2477 xmlGenericError(xmlGenericErrorContext,
2478 "%s is a Boolean\n", arg);
2479 break;
2480 case XPATH_NUMBER:
2481 xmlGenericError(xmlGenericErrorContext,
2482 "%s is a number\n", arg);
2483 break;
2484 case XPATH_STRING:
2485 xmlGenericError(xmlGenericErrorContext,
2486 "%s is a string\n", arg);
2487 break;
2488 case XPATH_POINT:
2489 xmlGenericError(xmlGenericErrorContext,
2490 "%s is a point\n", arg);
2491 break;
2492 case XPATH_RANGE:
2493 xmlGenericError(xmlGenericErrorContext,
2494 "%s is a range\n", arg);
2495 break;
2496 case XPATH_LOCATIONSET:
2497 xmlGenericError(xmlGenericErrorContext,
2498 "%s is a range\n", arg);
2499 break;
2500 case XPATH_USERS:
2501 xmlGenericError(xmlGenericErrorContext,
2502 "%s is user-defined\n", arg);
2503 break;
2504 case XPATH_XSLT_TREE:
2505 xmlGenericError(xmlGenericErrorContext,
2506 "%s is an XSLT value tree\n",
2507 arg);
2508 break;
2509 }
2510#ifdef LIBXML_XPATH_ENABLED
2511 xmlXPathFreeObject(list);
Daniel Veillard61d80a22001-04-27 17:13:01 +00002512#endif
Daniel Veillard78d12092001-10-11 09:12:24 +00002513 } else {
2514 xmlGenericError(xmlGenericErrorContext,
2515 "%s: no such node\n", arg);
2516 }
2517 ctxt->pctxt->node = NULL;
2518 }
2519 } else if (!strcmp(command, "cd")) {
2520 if (arg[0] == 0) {
2521 ctxt->node = (xmlNodePtr) ctxt->doc;
2522 } else {
2523#ifdef LIBXML_XPATH_ENABLED
2524 ctxt->pctxt->node = ctxt->node;
2525 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2526#else
2527 list = NULL;
2528#endif /* LIBXML_XPATH_ENABLED */
2529 if (list != NULL) {
2530 switch (list->type) {
2531 case XPATH_UNDEFINED:
2532 xmlGenericError(xmlGenericErrorContext,
2533 "%s: no such node\n", arg);
2534 break;
2535 case XPATH_NODESET:
Daniel Veillarda6825e82001-11-07 13:33:59 +00002536 if (list->nodesetval != NULL) {
2537 if (list->nodesetval->nodeNr == 1) {
2538 ctxt->node = list->nodesetval->nodeTab[0];
Daniel Veillard7a985a12003-07-06 17:57:42 +00002539 if ((ctxt->node != NULL) &&
2540 (ctxt->node->type ==
2541 XML_NAMESPACE_DECL)) {
2542 xmlGenericError(xmlGenericErrorContext,
2543 "cannot cd to namespace\n");
2544 ctxt->node = NULL;
2545 }
Daniel Veillarda6825e82001-11-07 13:33:59 +00002546 } else
2547 xmlGenericError(xmlGenericErrorContext,
2548 "%s is a %d Node Set\n",
2549 arg,
2550 list->nodesetval->nodeNr);
Daniel Veillard78d12092001-10-11 09:12:24 +00002551 } else
2552 xmlGenericError(xmlGenericErrorContext,
Daniel Veillarda6825e82001-11-07 13:33:59 +00002553 "%s is an empty Node Set\n",
2554 arg);
Daniel Veillard78d12092001-10-11 09:12:24 +00002555 break;
2556 case XPATH_BOOLEAN:
2557 xmlGenericError(xmlGenericErrorContext,
2558 "%s is a Boolean\n", arg);
2559 break;
2560 case XPATH_NUMBER:
2561 xmlGenericError(xmlGenericErrorContext,
2562 "%s is a number\n", arg);
2563 break;
2564 case XPATH_STRING:
2565 xmlGenericError(xmlGenericErrorContext,
2566 "%s is a string\n", arg);
2567 break;
2568 case XPATH_POINT:
2569 xmlGenericError(xmlGenericErrorContext,
2570 "%s is a point\n", arg);
2571 break;
2572 case XPATH_RANGE:
2573 xmlGenericError(xmlGenericErrorContext,
2574 "%s is a range\n", arg);
2575 break;
2576 case XPATH_LOCATIONSET:
2577 xmlGenericError(xmlGenericErrorContext,
2578 "%s is a range\n", arg);
2579 break;
2580 case XPATH_USERS:
2581 xmlGenericError(xmlGenericErrorContext,
2582 "%s is user-defined\n", arg);
2583 break;
2584 case XPATH_XSLT_TREE:
2585 xmlGenericError(xmlGenericErrorContext,
2586 "%s is an XSLT value tree\n",
2587 arg);
2588 break;
2589 }
2590#ifdef LIBXML_XPATH_ENABLED
2591 xmlXPathFreeObject(list);
2592#endif
2593 } else {
2594 xmlGenericError(xmlGenericErrorContext,
2595 "%s: no such node\n", arg);
2596 }
2597 ctxt->pctxt->node = NULL;
2598 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002599#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillard78d12092001-10-11 09:12:24 +00002600 } else if (!strcmp(command, "cat")) {
2601 if (arg[0] == 0) {
2602 xmlShellCat(ctxt, NULL, ctxt->node, NULL);
2603 } else {
2604 ctxt->pctxt->node = ctxt->node;
2605#ifdef LIBXML_XPATH_ENABLED
2606 ctxt->pctxt->node = ctxt->node;
2607 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2608#else
2609 list = NULL;
2610#endif /* LIBXML_XPATH_ENABLED */
2611 if (list != NULL) {
2612 switch (list->type) {
2613 case XPATH_UNDEFINED:
2614 xmlGenericError(xmlGenericErrorContext,
2615 "%s: no such node\n", arg);
2616 break;
2617 case XPATH_NODESET:{
2618 int indx;
2619
Daniel Veillarda6825e82001-11-07 13:33:59 +00002620 if (list->nodesetval == NULL)
2621 break;
2622
Daniel Veillard78d12092001-10-11 09:12:24 +00002623 for (indx = 0;
2624 indx < list->nodesetval->nodeNr;
2625 indx++) {
2626 if (i > 0)
Daniel Veillard321be0c2002-10-08 21:26:42 +00002627 fprintf(ctxt->output, " -------\n");
Daniel Veillard78d12092001-10-11 09:12:24 +00002628 xmlShellCat(ctxt, NULL,
2629 list->nodesetval->
2630 nodeTab[indx], NULL);
2631 }
2632 break;
2633 }
2634 case XPATH_BOOLEAN:
2635 xmlGenericError(xmlGenericErrorContext,
2636 "%s is a Boolean\n", arg);
2637 break;
2638 case XPATH_NUMBER:
2639 xmlGenericError(xmlGenericErrorContext,
2640 "%s is a number\n", arg);
2641 break;
2642 case XPATH_STRING:
2643 xmlGenericError(xmlGenericErrorContext,
2644 "%s is a string\n", arg);
2645 break;
2646 case XPATH_POINT:
2647 xmlGenericError(xmlGenericErrorContext,
2648 "%s is a point\n", arg);
2649 break;
2650 case XPATH_RANGE:
2651 xmlGenericError(xmlGenericErrorContext,
2652 "%s is a range\n", arg);
2653 break;
2654 case XPATH_LOCATIONSET:
2655 xmlGenericError(xmlGenericErrorContext,
2656 "%s is a range\n", arg);
2657 break;
2658 case XPATH_USERS:
2659 xmlGenericError(xmlGenericErrorContext,
2660 "%s is user-defined\n", arg);
2661 break;
2662 case XPATH_XSLT_TREE:
2663 xmlGenericError(xmlGenericErrorContext,
2664 "%s is an XSLT value tree\n",
2665 arg);
2666 break;
2667 }
2668#ifdef LIBXML_XPATH_ENABLED
2669 xmlXPathFreeObject(list);
2670#endif
2671 } else {
2672 xmlGenericError(xmlGenericErrorContext,
2673 "%s: no such node\n", arg);
2674 }
2675 ctxt->pctxt->node = NULL;
2676 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002677#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard78d12092001-10-11 09:12:24 +00002678 } else {
2679 xmlGenericError(xmlGenericErrorContext,
2680 "Unknown command %s\n", command);
2681 }
2682 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00002683 }
2684#ifdef LIBXML_XPATH_ENABLED
2685 xmlXPathFreeContext(ctxt->pctxt);
2686#endif /* LIBXML_XPATH_ENABLED */
2687 if (ctxt->loaded) {
2688 xmlFreeDoc(ctxt->doc);
2689 }
Daniel Veillardb8c9be92001-07-09 16:01:19 +00002690 if (ctxt->filename != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002691 xmlFree(ctxt->filename);
Owen Taylor3473f882001-02-23 17:55:21 +00002692 xmlFree(ctxt);
2693 if (cmdline != NULL)
Daniel Veillard78d12092001-10-11 09:12:24 +00002694 free(cmdline); /* not xmlFree here ! */
Owen Taylor3473f882001-02-23 17:55:21 +00002695}
2696
2697#endif /* LIBXML_DEBUG_ENABLED */