2 * debugXML.c : This is a set of routines used for debugging the tree
3 * produced by the XML parser.
5 * See Copyright for the status of this software.
7 * Daniel Veillard <daniel@veillard.com>
12 #ifdef LIBXML_DEBUG_ENABLED
21 #include <libxml/xmlmemory.h>
22 #include <libxml/tree.h>
23 #include <libxml/parser.h>
24 #include <libxml/parserInternals.h>
25 #include <libxml/valid.h>
26 #include <libxml/debugXML.h>
27 #include <libxml/HTMLtree.h>
28 #include <libxml/HTMLparser.h>
29 #include <libxml/xmlerror.h>
30 #include <libxml/globals.h>
31 #include <libxml/xpathInternals.h>
35 * @output: the FILE * for the output
38 * Dumps informations about the string, shorten it if necessary
41 xmlDebugDumpString(FILE * output, const xmlChar * str)
48 fprintf(output, "(NULL)");
51 for (i = 0; i < 40; i++)
54 else if (IS_BLANK(str[i]))
56 else if (str[i] >= 0x80)
57 fprintf(output, "#%X", str[i]);
59 fputc(str[i], output);
60 fprintf(output, "...");
64 xmlDebugDumpDtdNode(FILE *output, xmlDtdPtr dtd, int depth) {
68 for (i = 0;((i < depth) && (i < 25));i++)
69 shift[2 * i] = shift[2 * i + 1] = ' ';
70 shift[2 * i] = shift[2 * i + 1] = 0;
72 fprintf(output, shift);
75 fprintf(output, "DTD node is NULL\n");
79 if (dtd->type != XML_DTD_NODE) {
80 fprintf(output, "PBM: not a DTD\n");
83 if (dtd->name != NULL)
84 fprintf(output, "DTD(%s)", dtd->name);
86 fprintf(output, "DTD");
87 if (dtd->ExternalID != NULL)
88 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
89 if (dtd->SystemID != NULL)
90 fprintf(output, ", SYSTEM %s", dtd->SystemID);
91 fprintf(output, "\n");
93 * Do a bit of checking
95 if (dtd->parent == NULL)
96 fprintf(output, "PBM: DTD has no parent\n");
98 fprintf(output, "PBM: DTD has no doc\n");
99 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
100 fprintf(output, "PBM: DTD doc differs from parent's one\n");
101 if (dtd->prev == NULL) {
102 if ((dtd->parent != NULL) && (dtd->parent->children != (xmlNodePtr)dtd))
103 fprintf(output, "PBM: DTD has no prev and not first of list\n");
105 if (dtd->prev->next != (xmlNodePtr) dtd)
106 fprintf(output, "PBM: DTD prev->next : back link wrong\n");
108 if (dtd->next == NULL) {
109 if ((dtd->parent != NULL) && (dtd->parent->last != (xmlNodePtr) dtd))
110 fprintf(output, "PBM: DTD has no next and not last of list\n");
112 if (dtd->next->prev != (xmlNodePtr) dtd)
113 fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
118 xmlDebugDumpAttrDecl(FILE *output, xmlAttributePtr attr, int depth) {
122 for (i = 0;((i < depth) && (i < 25));i++)
123 shift[2 * i] = shift[2 * i + 1] = ' ';
124 shift[2 * i] = shift[2 * i + 1] = 0;
126 fprintf(output, shift);
129 fprintf(output, "Attribute declaration is NULL\n");
132 if (attr->type != XML_ATTRIBUTE_DECL) {
133 fprintf(output, "PBM: not a Attr\n");
136 if (attr->name != NULL)
137 fprintf(output, "ATTRDECL(%s)", attr->name);
139 fprintf(output, "PBM ATTRDECL noname!!!");
140 if (attr->elem != NULL)
141 fprintf(output, " for %s", attr->elem);
143 fprintf(output, " PBM noelem!!!");
144 switch (attr->atype) {
145 case XML_ATTRIBUTE_CDATA:
146 fprintf(output, " CDATA");
148 case XML_ATTRIBUTE_ID:
149 fprintf(output, " ID");
151 case XML_ATTRIBUTE_IDREF:
152 fprintf(output, " IDREF");
154 case XML_ATTRIBUTE_IDREFS:
155 fprintf(output, " IDREFS");
157 case XML_ATTRIBUTE_ENTITY:
158 fprintf(output, " ENTITY");
160 case XML_ATTRIBUTE_ENTITIES:
161 fprintf(output, " ENTITIES");
163 case XML_ATTRIBUTE_NMTOKEN:
164 fprintf(output, " NMTOKEN");
166 case XML_ATTRIBUTE_NMTOKENS:
167 fprintf(output, " NMTOKENS");
169 case XML_ATTRIBUTE_ENUMERATION:
170 fprintf(output, " ENUMERATION");
172 case XML_ATTRIBUTE_NOTATION:
173 fprintf(output, " NOTATION ");
176 if (attr->tree != NULL) {
178 xmlEnumerationPtr cur = attr->tree;
180 for (indx = 0;indx < 5; indx++) {
182 fprintf(output, "|%s", cur->name);
184 fprintf(output, " (%s", cur->name);
186 if (cur == NULL) break;
189 fprintf(output, ")");
191 fprintf(output, "...)");
194 case XML_ATTRIBUTE_NONE:
196 case XML_ATTRIBUTE_REQUIRED:
197 fprintf(output, " REQUIRED");
199 case XML_ATTRIBUTE_IMPLIED:
200 fprintf(output, " IMPLIED");
202 case XML_ATTRIBUTE_FIXED:
203 fprintf(output, " FIXED");
206 if (attr->defaultValue != NULL) {
207 fprintf(output, "\"");
208 xmlDebugDumpString(output, attr->defaultValue);
209 fprintf(output, "\"");
211 fprintf(output, "\n");
214 * Do a bit of checking
216 if (attr->parent == NULL)
217 fprintf(output, "PBM: Attr has no parent\n");
218 if (attr->doc == NULL)
219 fprintf(output, "PBM: Attr has no doc\n");
220 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
221 fprintf(output, "PBM: Attr doc differs from parent's one\n");
222 if (attr->prev == NULL) {
223 if ((attr->parent != NULL) && (attr->parent->children != (xmlNodePtr)attr))
224 fprintf(output, "PBM: Attr has no prev and not first of list\n");
226 if (attr->prev->next != (xmlNodePtr) attr)
227 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
229 if (attr->next == NULL) {
230 if ((attr->parent != NULL) && (attr->parent->last != (xmlNodePtr) attr))
231 fprintf(output, "PBM: Attr has no next and not last of list\n");
233 if (attr->next->prev != (xmlNodePtr) attr)
234 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
239 xmlDebugDumpElemDecl(FILE *output, xmlElementPtr elem, int depth) {
243 for (i = 0;((i < depth) && (i < 25));i++)
244 shift[2 * i] = shift[2 * i + 1] = ' ';
245 shift[2 * i] = shift[2 * i + 1] = 0;
247 fprintf(output, shift);
250 fprintf(output, "Element declaration is NULL\n");
253 if (elem->type != XML_ELEMENT_DECL) {
254 fprintf(output, "PBM: not a Elem\n");
257 if (elem->name != NULL) {
258 fprintf(output, "ELEMDECL(");
259 xmlDebugDumpString(output, elem->name);
260 fprintf(output, ")");
262 fprintf(output, "PBM ELEMDECL noname!!!");
263 switch (elem->etype) {
264 case XML_ELEMENT_TYPE_UNDEFINED:
265 fprintf(output, ", UNDEFINED");
267 case XML_ELEMENT_TYPE_EMPTY:
268 fprintf(output, ", EMPTY");
270 case XML_ELEMENT_TYPE_ANY:
271 fprintf(output, ", ANY");
273 case XML_ELEMENT_TYPE_MIXED:
274 fprintf(output, ", MIXED ");
276 case XML_ELEMENT_TYPE_ELEMENT:
277 fprintf(output, ", MIXED ");
280 if ((elem->type != XML_ELEMENT_NODE) &&
281 (elem->content != NULL)) {
285 xmlSnprintfElementContent(buf, 5000, elem->content, 1);
287 fprintf(output, "%s", buf);
289 fprintf(output, "\n");
292 * Do a bit of checking
294 if (elem->parent == NULL)
295 fprintf(output, "PBM: Elem has no parent\n");
296 if (elem->doc == NULL)
297 fprintf(output, "PBM: Elem has no doc\n");
298 if ((elem->parent != NULL) && (elem->doc != elem->parent->doc))
299 fprintf(output, "PBM: Elem doc differs from parent's one\n");
300 if (elem->prev == NULL) {
301 if ((elem->parent != NULL) && (elem->parent->children != (xmlNodePtr)elem))
302 fprintf(output, "PBM: Elem has no prev and not first of list\n");
304 if (elem->prev->next != (xmlNodePtr) elem)
305 fprintf(output, "PBM: Elem prev->next : back link wrong\n");
307 if (elem->next == NULL) {
308 if ((elem->parent != NULL) && (elem->parent->last != (xmlNodePtr) elem))
309 fprintf(output, "PBM: Elem has no next and not last of list\n");
311 if (elem->next->prev != (xmlNodePtr) elem)
312 fprintf(output, "PBM: Elem next->prev : forward link wrong\n");
317 xmlDebugDumpEntityDecl(FILE *output, xmlEntityPtr ent, int depth) {
321 for (i = 0;((i < depth) && (i < 25));i++)
322 shift[2 * i] = shift[2 * i + 1] = ' ';
323 shift[2 * i] = shift[2 * i + 1] = 0;
325 fprintf(output, shift);
328 fprintf(output, "Entity declaration is NULL\n");
331 if (ent->type != XML_ENTITY_DECL) {
332 fprintf(output, "PBM: not a Entity decl\n");
335 if (ent->name != NULL) {
336 fprintf(output, "ENTITYDECL(");
337 xmlDebugDumpString(output, ent->name);
338 fprintf(output, ")");
340 fprintf(output, "PBM ENTITYDECL noname!!!");
341 switch (ent->etype) {
342 case XML_INTERNAL_GENERAL_ENTITY:
343 fprintf(output, ", internal\n");
345 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
346 fprintf(output, ", external parsed\n");
348 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
349 fprintf(output, ", unparsed\n");
351 case XML_INTERNAL_PARAMETER_ENTITY:
352 fprintf(output, ", parameter\n");
354 case XML_EXTERNAL_PARAMETER_ENTITY:
355 fprintf(output, ", external parameter\n");
357 case XML_INTERNAL_PREDEFINED_ENTITY:
358 fprintf(output, ", predefined\n");
361 if (ent->ExternalID) {
362 fprintf(output, shift);
363 fprintf(output, " ExternalID=%s\n", ent->ExternalID);
366 fprintf(output, shift);
367 fprintf(output, " SystemID=%s\n", ent->SystemID);
369 if (ent->URI != NULL) {
370 fprintf(output, shift);
371 fprintf(output, " URI=%s\n", ent->URI);
374 fprintf(output, shift);
375 fprintf(output, " content=");
376 xmlDebugDumpString(output, ent->content);
377 fprintf(output, "\n");
381 * Do a bit of checking
383 if (ent->parent == NULL)
384 fprintf(output, "PBM: Ent has no parent\n");
385 if (ent->doc == NULL)
386 fprintf(output, "PBM: Ent has no doc\n");
387 if ((ent->parent != NULL) && (ent->doc != ent->parent->doc))
388 fprintf(output, "PBM: Ent doc differs from parent's one\n");
389 if (ent->prev == NULL) {
390 if ((ent->parent != NULL) && (ent->parent->children != (xmlNodePtr)ent))
391 fprintf(output, "PBM: Ent has no prev and not first of list\n");
393 if (ent->prev->next != (xmlNodePtr) ent)
394 fprintf(output, "PBM: Ent prev->next : back link wrong\n");
396 if (ent->next == NULL) {
397 if ((ent->parent != NULL) && (ent->parent->last != (xmlNodePtr) ent))
398 fprintf(output, "PBM: Ent has no next and not last of list\n");
400 if (ent->next->prev != (xmlNodePtr) ent)
401 fprintf(output, "PBM: Ent next->prev : forward link wrong\n");
406 xmlDebugDumpNamespace(FILE *output, xmlNsPtr ns, int depth) {
410 for (i = 0;((i < depth) && (i < 25));i++)
411 shift[2 * i] = shift[2 * i + 1] = ' ';
412 shift[2 * i] = shift[2 * i + 1] = 0;
414 fprintf(output, shift);
417 fprintf(output, "namespace node is NULL\n");
420 if (ns->type != XML_NAMESPACE_DECL) {
421 fprintf(output, "invalid namespace node %d\n", ns->type);
424 if (ns->href == NULL) {
425 if (ns->prefix != NULL)
426 fprintf(output, "incomplete namespace %s href=NULL\n", ns->prefix);
428 fprintf(output, "incomplete default namespace href=NULL\n");
430 if (ns->prefix != NULL)
431 fprintf(output, "namespace %s href=", ns->prefix);
433 fprintf(output, "default namespace href=");
435 xmlDebugDumpString(output, ns->href);
436 fprintf(output, "\n");
441 xmlDebugDumpNamespaceList(FILE *output, xmlNsPtr ns, int depth) {
443 xmlDebugDumpNamespace(output, ns, depth);
449 xmlDebugDumpEntity(FILE *output, xmlEntityPtr ent, int depth) {
453 for (i = 0;((i < depth) && (i < 25));i++)
454 shift[2 * i] = shift[2 * i + 1] = ' ';
455 shift[2 * i] = shift[2 * i + 1] = 0;
457 fprintf(output, shift);
460 fprintf(output, "Entity is NULL\n");
463 switch (ent->etype) {
464 case XML_INTERNAL_GENERAL_ENTITY:
465 fprintf(output, "INTERNAL_GENERAL_ENTITY ");
467 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
468 fprintf(output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
470 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
471 fprintf(output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
473 case XML_INTERNAL_PARAMETER_ENTITY:
474 fprintf(output, "INTERNAL_PARAMETER_ENTITY ");
476 case XML_EXTERNAL_PARAMETER_ENTITY:
477 fprintf(output, "EXTERNAL_PARAMETER_ENTITY ");
480 fprintf(output, "ENTITY_%d ! ", ent->etype);
482 fprintf(output, "%s\n", ent->name);
483 if (ent->ExternalID) {
484 fprintf(output, shift);
485 fprintf(output, "ExternalID=%s\n", ent->ExternalID);
488 fprintf(output, shift);
489 fprintf(output, "SystemID=%s\n", ent->SystemID);
492 fprintf(output, shift);
493 fprintf(output, "URI=%s\n", ent->URI);
496 fprintf(output, shift);
497 fprintf(output, "content=");
498 xmlDebugDumpString(output, ent->content);
499 fprintf(output, "\n");
505 * @output: the FILE * for the output
506 * @attr: the attribute
507 * @depth: the indentation level.
509 * Dumps debug information for the attribute
512 xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
516 for (i = 0;((i < depth) && (i < 25));i++)
517 shift[2 * i] = shift[2 * i + 1] = ' ';
518 shift[2 * i] = shift[2 * i + 1] = 0;
520 fprintf(output, shift);
523 fprintf(output, "Attr is NULL");
526 fprintf(output, "ATTRIBUTE ");
527 xmlDebugDumpString(output, attr->name);
528 fprintf(output, "\n");
529 if (attr->children != NULL)
530 xmlDebugDumpNodeList(output, attr->children, depth + 1);
533 * Do a bit of checking
535 if (attr->parent == NULL)
536 fprintf(output, "PBM: Attr has no parent\n");
537 if (attr->doc == NULL)
538 fprintf(output, "PBM: Attr has no doc\n");
539 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
540 fprintf(output, "PBM: Attr doc differs from parent's one\n");
541 if (attr->prev == NULL) {
542 if ((attr->parent != NULL) && (attr->parent->properties != attr))
543 fprintf(output, "PBM: Attr has no prev and not first of list\n");
545 if (attr->prev->next != attr)
546 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
548 if (attr->next != NULL) {
549 if (attr->next->prev != attr)
550 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
555 * xmlDebugDumpAttrList:
556 * @output: the FILE * for the output
557 * @attr: the attribute list
558 * @depth: the indentation level.
560 * Dumps debug information for the attribute list
563 xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth)
567 while (attr != NULL) {
568 xmlDebugDumpAttr(output, attr, depth);
574 * xmlDebugDumpOneNode:
575 * @output: the FILE * for the output
577 * @depth: the indentation level.
579 * Dumps debug information for the element node, it is not recursive
582 xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth)
589 for (i = 0; ((i < depth) && (i < 25)); i++)
590 shift[2 * i] = shift[2 * i + 1] = ' ';
591 shift[2 * i] = shift[2 * i + 1] = 0;
594 fprintf(output, shift);
595 fprintf(output, "node is NULL\n");
598 switch (node->type) {
599 case XML_ELEMENT_NODE:
600 fprintf(output, shift);
601 fprintf(output, "ELEMENT ");
602 if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
603 xmlDebugDumpString(output, node->ns->prefix);
604 fprintf(output, ":");
606 xmlDebugDumpString(output, node->name);
607 fprintf(output, "\n");
609 case XML_ATTRIBUTE_NODE:
610 fprintf(output, shift);
611 fprintf(output, "Error, ATTRIBUTE found here\n");
614 fprintf(output, shift);
615 if (node->name == (const xmlChar *) xmlStringTextNoenc)
616 fprintf(output, "TEXT no enc\n");
618 fprintf(output, "TEXT\n");
620 case XML_CDATA_SECTION_NODE:
621 fprintf(output, shift);
622 fprintf(output, "CDATA_SECTION\n");
624 case XML_ENTITY_REF_NODE:
625 fprintf(output, shift);
626 fprintf(output, "ENTITY_REF(%s)\n", node->name);
628 case XML_ENTITY_NODE:
629 fprintf(output, shift);
630 fprintf(output, "ENTITY\n");
633 fprintf(output, shift);
634 fprintf(output, "PI %s\n", node->name);
636 case XML_COMMENT_NODE:
637 fprintf(output, shift);
638 fprintf(output, "COMMENT\n");
640 case XML_DOCUMENT_NODE:
641 case XML_HTML_DOCUMENT_NODE:
642 fprintf(output, shift);
643 fprintf(output, "Error, DOCUMENT found here\n");
645 case XML_DOCUMENT_TYPE_NODE:
646 fprintf(output, shift);
647 fprintf(output, "DOCUMENT_TYPE\n");
649 case XML_DOCUMENT_FRAG_NODE:
650 fprintf(output, shift);
651 fprintf(output, "DOCUMENT_FRAG\n");
653 case XML_NOTATION_NODE:
654 fprintf(output, shift);
655 fprintf(output, "NOTATION\n");
658 xmlDebugDumpDtdNode(output, (xmlDtdPtr) node, depth);
660 case XML_ELEMENT_DECL:
661 xmlDebugDumpElemDecl(output, (xmlElementPtr) node, depth);
663 case XML_ATTRIBUTE_DECL:
664 xmlDebugDumpAttrDecl(output, (xmlAttributePtr) node, depth);
666 case XML_ENTITY_DECL:
667 xmlDebugDumpEntityDecl(output, (xmlEntityPtr) node, depth);
669 case XML_NAMESPACE_DECL:
670 xmlDebugDumpNamespace(output, (xmlNsPtr) node, depth);
672 case XML_XINCLUDE_START:
673 fprintf(output, shift);
674 fprintf(output, "INCLUDE START\n");
676 case XML_XINCLUDE_END:
677 fprintf(output, shift);
678 fprintf(output, "INCLUDE END\n");
681 fprintf(output, shift);
682 fprintf(output, "NODE_%d !!!\n", node->type);
685 if (node->doc == NULL) {
686 fprintf(output, shift);
687 fprintf(output, "doc == NULL !!!\n");
689 if (node->nsDef != NULL)
690 xmlDebugDumpNamespaceList(output, node->nsDef, depth + 1);
691 if (node->properties != NULL)
692 xmlDebugDumpAttrList(output, node->properties, depth + 1);
693 if (node->type != XML_ENTITY_REF_NODE) {
694 if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
695 shift[2 * i] = shift[2 * i + 1] = ' ';
696 shift[2 * i + 2] = shift[2 * i + 3] = 0;
697 fprintf(output, shift);
698 fprintf(output, "content=");
699 xmlDebugDumpString(output, node->content);
700 fprintf(output, "\n");
705 ent = xmlGetDocEntity(node->doc, node->name);
707 xmlDebugDumpEntity(output, ent, depth + 1);
710 * Do a bit of checking
712 if (node->parent == NULL)
713 fprintf(output, "PBM: Node has no parent\n");
714 if (node->doc == NULL)
715 fprintf(output, "PBM: Node has no doc\n");
716 if ((node->parent != NULL) && (node->doc != node->parent->doc))
717 fprintf(output, "PBM: Node doc differs from parent's one\n");
718 if (node->prev == NULL) {
719 if ((node->parent != NULL) && (node->parent->children != node))
721 "PBM: Node has no prev and not first of list\n");
723 if (node->prev->next != node)
724 fprintf(output, "PBM: Node prev->next : back link wrong\n");
726 if (node->next == NULL) {
727 if ((node->parent != NULL) && (node->parent->last != node))
729 "PBM: Node has no next and not last of list\n");
731 if (node->next->prev != node)
732 fprintf(output, "PBM: Node next->prev : forward link wrong\n");
738 * @output: the FILE * for the output
740 * @depth: the indentation level.
742 * Dumps debug information for the element node, it is recursive
745 xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth)
753 for (i = 0; ((i < depth) && (i < 25)); i++)
754 shift[2 * i] = shift[2 * i + 1] = ' ';
755 shift[2 * i] = shift[2 * i + 1] = 0;
757 fprintf(output, shift);
758 fprintf(output, "node is NULL\n");
761 xmlDebugDumpOneNode(output, node, depth);
762 if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE))
763 xmlDebugDumpNodeList(output, node->children, depth + 1);
767 * xmlDebugDumpNodeList:
768 * @output: the FILE * for the output
769 * @node: the node list
770 * @depth: the indentation level.
772 * Dumps debug information for the list of element node, it is recursive
775 xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth)
779 while (node != NULL) {
780 xmlDebugDumpNode(output, node, depth);
787 * xmlDebugDumpDocumentHead:
788 * @output: the FILE * for the output
791 * Dumps debug information cncerning the document, not recursive
794 xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc)
799 fprintf(output, "DOCUMENT == NULL !\n");
804 case XML_ELEMENT_NODE:
805 fprintf(output, "Error, ELEMENT found here ");
807 case XML_ATTRIBUTE_NODE:
808 fprintf(output, "Error, ATTRIBUTE found here\n");
811 fprintf(output, "Error, TEXT\n");
813 case XML_CDATA_SECTION_NODE:
814 fprintf(output, "Error, CDATA_SECTION\n");
816 case XML_ENTITY_REF_NODE:
817 fprintf(output, "Error, ENTITY_REF\n");
819 case XML_ENTITY_NODE:
820 fprintf(output, "Error, ENTITY\n");
823 fprintf(output, "Error, PI\n");
825 case XML_COMMENT_NODE:
826 fprintf(output, "Error, COMMENT\n");
828 case XML_DOCUMENT_NODE:
829 fprintf(output, "DOCUMENT\n");
831 case XML_HTML_DOCUMENT_NODE:
832 fprintf(output, "HTML DOCUMENT\n");
834 case XML_DOCUMENT_TYPE_NODE:
835 fprintf(output, "Error, DOCUMENT_TYPE\n");
837 case XML_DOCUMENT_FRAG_NODE:
838 fprintf(output, "Error, DOCUMENT_FRAG\n");
840 case XML_NOTATION_NODE:
841 fprintf(output, "Error, NOTATION\n");
844 fprintf(output, "NODE_%d\n", doc->type);
846 if (doc->name != NULL) {
847 fprintf(output, "name=");
848 xmlDebugDumpString(output, BAD_CAST doc->name);
849 fprintf(output, "\n");
851 if (doc->version != NULL) {
852 fprintf(output, "version=");
853 xmlDebugDumpString(output, doc->version);
854 fprintf(output, "\n");
856 if (doc->encoding != NULL) {
857 fprintf(output, "encoding=");
858 xmlDebugDumpString(output, doc->encoding);
859 fprintf(output, "\n");
861 if (doc->URL != NULL) {
862 fprintf(output, "URL=");
863 xmlDebugDumpString(output, doc->URL);
864 fprintf(output, "\n");
867 fprintf(output, "standalone=true\n");
868 if (doc->oldNs != NULL)
869 xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
873 * xmlDebugDumpDocument:
874 * @output: the FILE * for the output
877 * Dumps debug information for the document, it's recursive
880 xmlDebugDumpDocument(FILE * output, xmlDocPtr doc)
885 fprintf(output, "DOCUMENT == NULL !\n");
888 xmlDebugDumpDocumentHead(output, doc);
889 if (((doc->type == XML_DOCUMENT_NODE) ||
890 (doc->type == XML_HTML_DOCUMENT_NODE)) && (doc->children != NULL))
891 xmlDebugDumpNodeList(output, doc->children, 1);
896 * @output: the FILE * for the output
899 * Dumps debug information for the DTD
902 xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd)
907 fprintf(output, "DTD is NULL\n");
910 if (dtd->type != XML_DTD_NODE) {
911 fprintf(output, "PBM: not a DTD\n");
914 if (dtd->name != NULL)
915 fprintf(output, "DTD(%s)", dtd->name);
917 fprintf(output, "DTD");
918 if (dtd->ExternalID != NULL)
919 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
920 if (dtd->SystemID != NULL)
921 fprintf(output, ", SYSTEM %s", dtd->SystemID);
922 fprintf(output, "\n");
924 * Do a bit of checking
926 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
927 fprintf(output, "PBM: DTD doc differs from parent's one\n");
928 if (dtd->prev == NULL) {
929 if ((dtd->parent != NULL)
930 && (dtd->parent->children != (xmlNodePtr) dtd))
932 "PBM: DTD has no prev and not first of list\n");
934 if (dtd->prev->next != (xmlNodePtr) dtd)
935 fprintf(output, "PBM: DTD prev->next : back link wrong\n");
937 if (dtd->next == NULL) {
938 if ((dtd->parent != NULL)
939 && (dtd->parent->last != (xmlNodePtr) dtd))
940 fprintf(output, "PBM: DTD has no next and not last of list\n");
942 if (dtd->next->prev != (xmlNodePtr) dtd)
943 fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
945 if (dtd->children == NULL)
946 fprintf(output, " DTD is empty\n");
948 xmlDebugDumpNodeList(output, dtd->children, 1);
952 xmlDebugDumpEntityCallback(xmlEntityPtr cur, FILE *output) {
954 fprintf(output, "Entity is NULL");
957 fprintf(output, "%s : ", cur->name);
958 switch (cur->etype) {
959 case XML_INTERNAL_GENERAL_ENTITY:
960 fprintf(output, "INTERNAL GENERAL, ");
962 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
963 fprintf(output, "EXTERNAL PARSED, ");
965 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
966 fprintf(output, "EXTERNAL UNPARSED, ");
968 case XML_INTERNAL_PARAMETER_ENTITY:
969 fprintf(output, "INTERNAL PARAMETER, ");
971 case XML_EXTERNAL_PARAMETER_ENTITY:
972 fprintf(output, "EXTERNAL PARAMETER, ");
975 fprintf(output, "UNKNOWN TYPE %d",
978 if (cur->ExternalID != NULL)
979 fprintf(output, "ID \"%s\"", cur->ExternalID);
980 if (cur->SystemID != NULL)
981 fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
982 if (cur->orig != NULL)
983 fprintf(output, "\n orig \"%s\"", cur->orig);
984 if ((cur->type != XML_ELEMENT_NODE) &&
985 (cur->content != NULL))
986 fprintf(output, "\n content \"%s\"", cur->content);
987 fprintf(output, "\n");
991 * xmlDebugDumpEntities:
992 * @output: the FILE * for the output
995 * Dumps debug information for all the entities in use by the document
998 xmlDebugDumpEntities(FILE * output, xmlDocPtr doc)
1003 fprintf(output, "DOCUMENT == NULL !\n");
1007 switch (doc->type) {
1008 case XML_ELEMENT_NODE:
1009 fprintf(output, "Error, ELEMENT found here ");
1011 case XML_ATTRIBUTE_NODE:
1012 fprintf(output, "Error, ATTRIBUTE found here\n");
1015 fprintf(output, "Error, TEXT\n");
1017 case XML_CDATA_SECTION_NODE:
1018 fprintf(output, "Error, CDATA_SECTION\n");
1020 case XML_ENTITY_REF_NODE:
1021 fprintf(output, "Error, ENTITY_REF\n");
1023 case XML_ENTITY_NODE:
1024 fprintf(output, "Error, ENTITY\n");
1027 fprintf(output, "Error, PI\n");
1029 case XML_COMMENT_NODE:
1030 fprintf(output, "Error, COMMENT\n");
1032 case XML_DOCUMENT_NODE:
1033 fprintf(output, "DOCUMENT\n");
1035 case XML_HTML_DOCUMENT_NODE:
1036 fprintf(output, "HTML DOCUMENT\n");
1038 case XML_DOCUMENT_TYPE_NODE:
1039 fprintf(output, "Error, DOCUMENT_TYPE\n");
1041 case XML_DOCUMENT_FRAG_NODE:
1042 fprintf(output, "Error, DOCUMENT_FRAG\n");
1044 case XML_NOTATION_NODE:
1045 fprintf(output, "Error, NOTATION\n");
1048 fprintf(output, "NODE_%d\n", doc->type);
1050 if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
1051 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1052 doc->intSubset->entities;
1054 fprintf(output, "Entities in internal subset\n");
1055 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1058 fprintf(output, "No entities in internal subset\n");
1059 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
1060 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1061 doc->extSubset->entities;
1063 fprintf(output, "Entities in external subset\n");
1064 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1067 fprintf(output, "No entities in external subset\n");
1072 * @node: the node to count
1074 * Count the children of @node.
1076 * Returns the number of children of @node.
1079 xmlLsCountNode(xmlNodePtr node) {
1081 xmlNodePtr list = NULL;
1086 switch (node->type) {
1087 case XML_ELEMENT_NODE:
1088 list = node->children;
1090 case XML_DOCUMENT_NODE:
1091 case XML_HTML_DOCUMENT_NODE:
1092 #ifdef LIBXML_DOCB_ENABLED
1093 case XML_DOCB_DOCUMENT_NODE:
1095 list = ((xmlDocPtr) node)->children;
1097 case XML_ATTRIBUTE_NODE:
1098 list = ((xmlAttrPtr) node)->children;
1101 case XML_CDATA_SECTION_NODE:
1103 case XML_COMMENT_NODE:
1104 if (node->content != NULL) {
1105 ret = xmlStrlen(node->content);
1108 case XML_ENTITY_REF_NODE:
1109 case XML_DOCUMENT_TYPE_NODE:
1110 case XML_ENTITY_NODE:
1111 case XML_DOCUMENT_FRAG_NODE:
1112 case XML_NOTATION_NODE:
1114 case XML_ELEMENT_DECL:
1115 case XML_ATTRIBUTE_DECL:
1116 case XML_ENTITY_DECL:
1117 case XML_NAMESPACE_DECL:
1118 case XML_XINCLUDE_START:
1119 case XML_XINCLUDE_END:
1123 for (;list != NULL;ret++)
1130 * @output: the FILE * for the output
1131 * @node: the node to dump
1133 * Dump to @output the type and name of @node.
1136 xmlLsOneNode(FILE *output, xmlNodePtr node) {
1138 fprintf(output, "NULL\n");
1141 switch (node->type) {
1142 case XML_ELEMENT_NODE:
1143 fprintf(output, "-");
1145 case XML_ATTRIBUTE_NODE:
1146 fprintf(output, "a");
1149 fprintf(output, "t");
1151 case XML_CDATA_SECTION_NODE:
1152 fprintf(output, "C");
1154 case XML_ENTITY_REF_NODE:
1155 fprintf(output, "e");
1157 case XML_ENTITY_NODE:
1158 fprintf(output, "E");
1161 fprintf(output, "p");
1163 case XML_COMMENT_NODE:
1164 fprintf(output, "c");
1166 case XML_DOCUMENT_NODE:
1167 fprintf(output, "d");
1169 case XML_HTML_DOCUMENT_NODE:
1170 fprintf(output, "h");
1172 case XML_DOCUMENT_TYPE_NODE:
1173 fprintf(output, "T");
1175 case XML_DOCUMENT_FRAG_NODE:
1176 fprintf(output, "F");
1178 case XML_NOTATION_NODE:
1179 fprintf(output, "N");
1181 case XML_NAMESPACE_DECL:
1182 fprintf(output, "n");
1185 fprintf(output, "?");
1187 if (node->type != XML_NAMESPACE_DECL) {
1188 if (node->properties != NULL)
1189 fprintf(output, "a");
1191 fprintf(output, "-");
1192 if (node->nsDef != NULL)
1193 fprintf(output, "n");
1195 fprintf(output, "-");
1198 fprintf(output, " %8d ", xmlLsCountNode(node));
1200 switch (node->type) {
1201 case XML_ELEMENT_NODE:
1202 if (node->name != NULL)
1203 fprintf(output, "%s", node->name);
1205 case XML_ATTRIBUTE_NODE:
1206 if (node->name != NULL)
1207 fprintf(output, "%s", node->name);
1210 if (node->content != NULL) {
1211 xmlDebugDumpString(output, node->content);
1214 case XML_CDATA_SECTION_NODE:
1216 case XML_ENTITY_REF_NODE:
1217 if (node->name != NULL)
1218 fprintf(output, "%s", node->name);
1220 case XML_ENTITY_NODE:
1221 if (node->name != NULL)
1222 fprintf(output, "%s", node->name);
1225 if (node->name != NULL)
1226 fprintf(output, "%s", node->name);
1228 case XML_COMMENT_NODE:
1230 case XML_DOCUMENT_NODE:
1232 case XML_HTML_DOCUMENT_NODE:
1234 case XML_DOCUMENT_TYPE_NODE:
1236 case XML_DOCUMENT_FRAG_NODE:
1238 case XML_NOTATION_NODE:
1240 case XML_NAMESPACE_DECL: {
1241 xmlNsPtr ns = (xmlNsPtr) node;
1243 if (ns->prefix == NULL)
1244 fprintf(output, "default -> %s", ns->href);
1246 fprintf(output, "%s -> %s", ns->prefix, ns->href);
1250 if (node->name != NULL)
1251 fprintf(output, "%s", node->name);
1253 fprintf(output, "\n");
1258 * @boolval: a bool to turn into text
1260 * Convenient way to turn bool into text
1262 * Returns a pointer to either "True" or "False"
1265 xmlBoolToText(int boolval)
1273 /****************************************************************
1275 * The XML shell related functions *
1277 ****************************************************************/
1282 * TODO: Improvement/cleanups for the XML shell
1283 * - allow to shell out an editor on a subpart
1284 * - cleanup function registrations (with help) and calling
1285 * - provide registration routines
1289 * xmlShellPrintXPathError:
1290 * @errorType: valid xpath error id
1291 * @arg: the argument that cause xpath to fail
1293 * Print the xpath error to libxml default error channel
1296 xmlShellPrintXPathError(int errorType, const char *arg)
1298 const char *default_arg = "Result";
1303 switch (errorType) {
1304 case XPATH_UNDEFINED:
1305 xmlGenericError(xmlGenericErrorContext,
1306 "%s: no such node\n", arg);
1310 xmlGenericError(xmlGenericErrorContext,
1311 "%s is a Boolean\n", arg);
1314 xmlGenericError(xmlGenericErrorContext,
1315 "%s is a number\n", arg);
1318 xmlGenericError(xmlGenericErrorContext,
1319 "%s is a string\n", arg);
1322 xmlGenericError(xmlGenericErrorContext,
1323 "%s is a point\n", arg);
1326 xmlGenericError(xmlGenericErrorContext,
1327 "%s is a range\n", arg);
1329 case XPATH_LOCATIONSET:
1330 xmlGenericError(xmlGenericErrorContext,
1331 "%s is a range\n", arg);
1334 xmlGenericError(xmlGenericErrorContext,
1335 "%s is user-defined\n", arg);
1337 case XPATH_XSLT_TREE:
1338 xmlGenericError(xmlGenericErrorContext,
1339 "%s is an XSLT value tree\n", arg);
1342 xmlGenericError(xmlGenericErrorContext,
1343 "Try casting the result string function (xpath builtin)\n",
1349 * xmlShellPrintNodeCtxt:
1350 * @ctxt : a non-null shell context
1351 * @node : a non-null node to print to the output FILE
1353 * Print node to the output FILE
1356 xmlShellPrintNodeCtxt(xmlShellCtxtPtr ctxt,xmlNodePtr node)
1367 if (node->type == XML_DOCUMENT_NODE)
1368 xmlDocDump(fp, (xmlDocPtr) node);
1369 else if (node->type == XML_ATTRIBUTE_NODE)
1370 xmlDebugDumpAttrList(fp, (xmlAttrPtr) node, 0);
1372 xmlElemDump(fp, node->doc, node);
1378 * xmlShellPrintNode:
1379 * @node : a non-null node to print to the output FILE
1381 * Print node to the output FILE
1384 xmlShellPrintNode(xmlNodePtr node)
1386 xmlShellPrintNodeCtxt(NULL, node);
1390 * xmlShellPrintXPathResultCtxt:
1391 * @ctxt: a valid shell context
1392 * @list: a valid result generated by an xpath evaluation
1394 * Prints result to the output FILE
1397 xmlShellPrintXPathResultCtxt(xmlShellCtxtPtr ctxt,xmlXPathObjectPtr list)
1404 switch (list->type) {
1405 case XPATH_NODESET:{
1408 if (list->nodesetval) {
1409 for (indx = 0; indx < list->nodesetval->nodeNr;
1412 fprintf(stderr, " -------\n");
1413 xmlShellPrintNodeCtxt(ctxt,
1414 list->nodesetval->nodeTab[indx]);
1417 xmlGenericError(xmlGenericErrorContext,
1418 "Empty node set\n");
1423 xmlGenericError(xmlGenericErrorContext,
1424 "Is a Boolean:%s\n",
1425 xmlBoolToText(list->boolval));
1428 xmlGenericError(xmlGenericErrorContext,
1429 "Is a number:%0g\n", list->floatval);
1432 xmlGenericError(xmlGenericErrorContext,
1433 "Is a string:%s\n", list->stringval);
1437 xmlShellPrintXPathError(list->type, NULL);
1443 * xmlShellPrintXPathResult:
1444 * @list: a valid result generated by an xpath evaluation
1446 * Prints result to the output FILE
1449 xmlShellPrintXPathResult(xmlXPathObjectPtr list)
1451 xmlShellPrintXPathResultCtxt(NULL, list);
1456 * @ctxt: the shell context
1461 * Implements the XML shell function "ls"
1462 * Does an Unix like listing of the given node (like a directory)
1467 xmlShellList(xmlShellCtxtPtr ctxt,
1468 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1469 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1475 fprintf(ctxt->output, "NULL\n");
1478 if ((node->type == XML_DOCUMENT_NODE) ||
1479 (node->type == XML_HTML_DOCUMENT_NODE)) {
1480 cur = ((xmlDocPtr) node)->children;
1481 } else if (node->type == XML_NAMESPACE_DECL) {
1482 xmlLsOneNode(ctxt->output, node);
1484 } else if (node->children != NULL) {
1485 cur = node->children;
1487 xmlLsOneNode(ctxt->output, node);
1490 while (cur != NULL) {
1491 xmlLsOneNode(ctxt->output, cur);
1499 * @ctxt: the shell context
1504 * Implements the XML shell function "base"
1505 * dumps the current XML base of the node
1510 xmlShellBase(xmlShellCtxtPtr ctxt,
1511 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1512 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1518 fprintf(ctxt->output, "NULL\n");
1522 base = xmlNodeGetBase(node->doc, node);
1525 fprintf(ctxt->output, " No base found !!!\n");
1527 fprintf(ctxt->output, "%s\n", base);
1535 * @ctxt: the shell context
1536 * @arg: the new base
1540 * Implements the XML shell function "setbase"
1541 * change the current XML base of the node
1546 xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1547 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1548 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1550 xmlNodeSetBase(node, (xmlChar*) arg);
1556 * @ctxt: the shell context
1557 * @arg: the string or regular expression to find
1561 * Implements the XML shell function "grep"
1562 * dumps informations about the node (namespace, attributes, content).
1567 xmlShellGrep(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1568 char *arg, xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1576 #ifdef LIBXML_REGEXP_ENABLED
1577 if ((xmlStrchr((xmlChar *) arg, '?')) ||
1578 (xmlStrchr((xmlChar *) arg, '*')) ||
1579 (xmlStrchr((xmlChar *) arg, '.')) ||
1580 (xmlStrchr((xmlChar *) arg, '['))) {
1583 while (node != NULL) {
1584 if (node->type == XML_COMMENT_NODE) {
1585 if (xmlStrstr(node->content, (xmlChar *) arg)) {
1587 fprintf(ctxt->output, "%s : ", xmlGetNodePath(node));
1588 xmlShellList(ctxt, NULL, node, NULL);
1590 } else if (node->type == XML_TEXT_NODE) {
1591 if (xmlStrstr(node->content, (xmlChar *) arg)) {
1593 fprintf(ctxt->output, "%s : ", xmlGetNodePath(node->parent));
1594 xmlShellList(ctxt, NULL, node->parent, NULL);
1599 * Browse the full subtree, deep first
1602 if ((node->type == XML_DOCUMENT_NODE) ||
1603 (node->type == XML_HTML_DOCUMENT_NODE)) {
1604 node = ((xmlDocPtr) node)->children;
1605 } else if ((node->children != NULL)
1606 && (node->type != XML_ENTITY_REF_NODE)) {
1608 node = node->children;
1609 } else if (node->next != NULL) {
1613 /* go up to parents->next if needed */
1614 while (node != NULL) {
1615 if (node->parent != NULL) {
1616 node = node->parent;
1618 if (node->next != NULL) {
1622 if (node->parent == NULL) {
1634 * @ctxt: the shell context
1639 * Implements the XML shell function "dir"
1640 * dumps informations about the node (namespace, attributes, content).
1645 xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1646 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1647 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1652 fprintf(ctxt->output, "NULL\n");
1655 if ((node->type == XML_DOCUMENT_NODE) ||
1656 (node->type == XML_HTML_DOCUMENT_NODE)) {
1657 xmlDebugDumpDocumentHead(ctxt->output, (xmlDocPtr) node);
1658 } else if (node->type == XML_ATTRIBUTE_NODE) {
1659 xmlDebugDumpAttr(ctxt->output, (xmlAttrPtr) node, 0);
1661 xmlDebugDumpOneNode(ctxt->output, node, 0);
1668 * @ctxt: the shell context
1673 * Implements the XML shell function "cat"
1674 * dumps the serialization node content (XML or HTML).
1679 xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
1680 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1685 fprintf(ctxt->output, "NULL\n");
1688 if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
1689 #ifdef LIBXML_HTML_ENABLED
1690 if (node->type == XML_HTML_DOCUMENT_NODE)
1691 htmlDocDump(ctxt->output, (htmlDocPtr) node);
1693 htmlNodeDumpFile(ctxt->output, ctxt->doc, node);
1695 if (node->type == XML_DOCUMENT_NODE)
1696 xmlDocDump(ctxt->output, (xmlDocPtr) node);
1698 xmlElemDump(ctxt->output, ctxt->doc, node);
1699 #endif /* LIBXML_HTML_ENABLED */
1701 if (node->type == XML_DOCUMENT_NODE)
1702 xmlDocDump(ctxt->output, (xmlDocPtr) node);
1704 xmlElemDump(ctxt->output, ctxt->doc, node);
1706 fprintf(ctxt->output, "\n");
1712 * @ctxt: the shell context
1713 * @filename: the file name
1717 * Implements the XML shell function "load"
1718 * loads a new document specified by the filename
1720 * Returns 0 or -1 if loading failed
1723 xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename,
1724 xmlNodePtr node ATTRIBUTE_UNUSED,
1725 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1730 if (ctxt->doc != NULL)
1731 html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
1734 #ifdef LIBXML_HTML_ENABLED
1735 doc = htmlParseFile(filename, NULL);
1737 fprintf(ctxt->output, "HTML support not compiled in\n");
1739 #endif /* LIBXML_HTML_ENABLED */
1741 doc = xmlParseFile(filename);
1744 if (ctxt->loaded == 1) {
1745 xmlFreeDoc(ctxt->doc);
1748 #ifdef LIBXML_XPATH_ENABLED
1749 xmlXPathFreeContext(ctxt->pctxt);
1750 #endif /* LIBXML_XPATH_ENABLED */
1751 xmlFree(ctxt->filename);
1753 ctxt->node = (xmlNodePtr) doc;
1754 #ifdef LIBXML_XPATH_ENABLED
1755 ctxt->pctxt = xmlXPathNewContext(doc);
1756 #endif /* LIBXML_XPATH_ENABLED */
1757 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
1765 * @ctxt: the shell context
1766 * @filename: the file name
1767 * @node: a node in the tree
1770 * Implements the XML shell function "write"
1771 * Write the current node to the filename, it saves the serialization
1772 * of the subtree under the @node specified
1774 * Returns 0 or -1 in case of error
1777 xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
1778 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1782 if ((filename == NULL) || (filename[0] == 0)) {
1783 xmlGenericError(xmlGenericErrorContext,
1784 "Write command requires a filename argument\n");
1788 if (access((char *) filename, W_OK)) {
1789 xmlGenericError(xmlGenericErrorContext,
1790 "Cannot write to %s\n", filename);
1794 switch (node->type) {
1795 case XML_DOCUMENT_NODE:
1796 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1797 xmlGenericError(xmlGenericErrorContext,
1798 "Failed to write to %s\n", filename);
1802 case XML_HTML_DOCUMENT_NODE:
1803 #ifdef LIBXML_HTML_ENABLED
1804 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1805 xmlGenericError(xmlGenericErrorContext,
1806 "Failed to write to %s\n", filename);
1810 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1811 xmlGenericError(xmlGenericErrorContext,
1812 "Failed to write to %s\n", filename);
1815 #endif /* LIBXML_HTML_ENABLED */
1820 f = fopen((char *) filename, "w");
1822 xmlGenericError(xmlGenericErrorContext,
1823 "Failed to write to %s\n", filename);
1826 xmlElemDump(f, ctxt->doc, node);
1835 * @ctxt: the shell context
1836 * @filename: the file name (optional)
1840 * Implements the XML shell function "save"
1841 * Write the current document to the filename, or it's original name
1843 * Returns 0 or -1 in case of error
1846 xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
1847 xmlNodePtr node ATTRIBUTE_UNUSED,
1848 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1850 if (ctxt->doc == NULL)
1852 if ((filename == NULL) || (filename[0] == 0))
1853 filename = ctxt->filename;
1855 if (access((char *) filename, W_OK)) {
1856 xmlGenericError(xmlGenericErrorContext,
1857 "Cannot save to %s\n", filename);
1861 switch (ctxt->doc->type) {
1862 case XML_DOCUMENT_NODE:
1863 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1864 xmlGenericError(xmlGenericErrorContext,
1865 "Failed to save to %s\n", filename);
1868 case XML_HTML_DOCUMENT_NODE:
1869 #ifdef LIBXML_HTML_ENABLED
1870 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1871 xmlGenericError(xmlGenericErrorContext,
1872 "Failed to save to %s\n", filename);
1875 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1876 xmlGenericError(xmlGenericErrorContext,
1877 "Failed to save to %s\n", filename);
1879 #endif /* LIBXML_HTML_ENABLED */
1882 xmlGenericError(xmlGenericErrorContext,
1883 "To save to subparts of a document use the 'write' command\n");
1892 * @ctxt: the shell context
1893 * @dtd: the DTD URI (optional)
1897 * Implements the XML shell function "validate"
1898 * Validate the document, if a DTD path is provided, then the validation
1899 * is done against the given DTD.
1901 * Returns 0 or -1 in case of error
1904 xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd,
1905 xmlNodePtr node ATTRIBUTE_UNUSED,
1906 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1911 vctxt.userData = stderr;
1912 vctxt.error = (xmlValidityErrorFunc) fprintf;
1913 vctxt.warning = (xmlValidityWarningFunc) fprintf;
1915 if ((dtd == NULL) || (dtd[0] == 0)) {
1916 res = xmlValidateDocument(&vctxt, ctxt->doc);
1920 subset = xmlParseDTD(NULL, (xmlChar *) dtd);
1921 if (subset != NULL) {
1922 res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
1932 * @ctxt: the shell context
1934 * @tree: a node defining a subtree
1937 * Implements the XML shell function "du"
1938 * show the structure of the subtree under node @tree
1939 * If @tree is null, the command works on the current node.
1941 * Returns 0 or -1 in case of error
1944 xmlShellDu(xmlShellCtxtPtr ctxt,
1945 char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree,
1946 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1957 while (node != NULL) {
1958 if ((node->type == XML_DOCUMENT_NODE) ||
1959 (node->type == XML_HTML_DOCUMENT_NODE)) {
1960 fprintf(ctxt->output, "/\n");
1961 } else if (node->type == XML_ELEMENT_NODE) {
1962 for (i = 0; i < indent; i++)
1963 fprintf(ctxt->output, " ");
1964 fprintf(ctxt->output, "%s\n", node->name);
1969 * Browse the full subtree, deep first
1972 if ((node->type == XML_DOCUMENT_NODE) ||
1973 (node->type == XML_HTML_DOCUMENT_NODE)) {
1974 node = ((xmlDocPtr) node)->children;
1975 } else if ((node->children != NULL)
1976 && (node->type != XML_ENTITY_REF_NODE)) {
1978 node = node->children;
1980 } else if ((node != tree) && (node->next != NULL)) {
1983 } else if (node != tree) {
1984 /* go up to parents->next if needed */
1985 while (node != tree) {
1986 if (node->parent != NULL) {
1987 node = node->parent;
1990 if ((node != tree) && (node->next != NULL)) {
1994 if (node->parent == NULL) {
2003 /* exit condition */
2014 * @ctxt: the shell context
2015 * @buffer: the output buffer
2019 * Implements the XML shell function "pwd"
2020 * Show the full path from the root to the node, if needed building
2021 * thumblers when similar elements exists at a given ancestor level.
2022 * The output is compatible with XPath commands.
2024 * Returns 0 or -1 in case of error
2027 xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
2028 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2035 path = xmlGetNodePath(node);
2040 * This test prevents buffer overflow, because this routine
2041 * is only called by xmlShell, in which the second argument is
2043 * It is a dirty hack before a cleaner solution is found.
2044 * Documentation should mention that the second argument must
2045 * be at least 500 chars long, and could be stripped if too long.
2047 snprintf(buffer, 499, "%s", path);
2056 * @doc: the initial document
2057 * @filename: the output buffer
2058 * @input: the line reading function
2059 * @output: the output FILE*, defaults to stdout if NULL
2061 * Implements the XML shell
2062 * This allow to load, validate, view, modify and save a document
2063 * using a environment similar to a UNIX commandline.
2066 xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
2069 char prompt[500] = "/ > ";
2070 char *cmdline = NULL, *cur;
2075 xmlShellCtxtPtr ctxt;
2076 xmlXPathObjectPtr list;
2080 if (filename == NULL)
2086 ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
2091 ctxt->input = input;
2092 ctxt->output = output;
2093 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
2094 ctxt->node = (xmlNodePtr) ctxt->doc;
2096 #ifdef LIBXML_XPATH_ENABLED
2097 ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
2098 if (ctxt->pctxt == NULL) {
2102 #endif /* LIBXML_XPATH_ENABLED */
2104 if (ctxt->node == (xmlNodePtr) ctxt->doc)
2105 snprintf(prompt, sizeof(prompt), "%s > ", "/");
2106 else if (ctxt->node->name)
2107 snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
2109 snprintf(prompt, sizeof(prompt), "? > ");
2110 prompt[sizeof(prompt) - 1] = 0;
2113 * Get a new command line
2115 cmdline = ctxt->input(prompt);
2116 if (cmdline == NULL)
2120 * Parse the command itself
2124 while ((*cur == ' ') || (*cur == '\t'))
2127 while ((*cur != ' ') && (*cur != '\t') &&
2128 (*cur != '\n') && (*cur != '\r')) {
2131 command[i++] = *cur++;
2139 * Parse the argument
2141 while ((*cur == ' ') || (*cur == '\t'))
2144 while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
2154 * start interpreting the command
2156 if (!strcmp(command, "exit"))
2158 if (!strcmp(command, "quit"))
2160 if (!strcmp(command, "bye"))
2162 if (!strcmp(command, "help")) {
2163 fprintf(ctxt->output, "\tbase display XML base of the node\n");
2164 fprintf(ctxt->output, "\tsetbase URI change the XML base of the node\n");
2165 fprintf(ctxt->output, "\tbye leave shell\n");
2166 fprintf(ctxt->output, "\tcat [node] display node or current node\n");
2167 fprintf(ctxt->output, "\tcd [path] change directory to path or to root\n");
2168 fprintf(ctxt->output, "\tdir [path] dumps informations about the node (namespace, attributes, content)\n");
2169 fprintf(ctxt->output, "\tdu [path] show the structure of the subtree under path or the current node\n");
2170 fprintf(ctxt->output, "\texit leave shell\n");
2171 fprintf(ctxt->output, "\thelp display this help\n");
2172 fprintf(ctxt->output, "\tfree display memory usage\n");
2173 fprintf(ctxt->output, "\tload [name] load a new document with name\n");
2174 fprintf(ctxt->output, "\tls [path] list contents of path or the current directory\n");
2175 #ifdef LIBXML_XPATH_ENABLED
2176 fprintf(ctxt->output, "\txpath expr evaluate the XPath expression in that context and print the result\n");
2177 #endif /* LIBXML_XPATH_ENABLED */
2178 fprintf(ctxt->output, "\tpwd display current working directory\n");
2179 fprintf(ctxt->output, "\tquit leave shell\n");
2180 fprintf(ctxt->output, "\tsave [name] save this document to name or the original name\n");
2181 fprintf(ctxt->output, "\tvalidate check the document for errors\n");
2182 fprintf(ctxt->output, "\twrite [name] write the current node to the filename\n");
2183 fprintf(ctxt->output, "\tgrep string search for a string in the subtree\n");
2184 } else if (!strcmp(command, "validate")) {
2185 xmlShellValidate(ctxt, arg, NULL, NULL);
2186 } else if (!strcmp(command, "load")) {
2187 xmlShellLoad(ctxt, arg, NULL, NULL);
2188 } else if (!strcmp(command, "save")) {
2189 xmlShellSave(ctxt, arg, NULL, NULL);
2190 } else if (!strcmp(command, "write")) {
2191 xmlShellWrite(ctxt, arg, NULL, NULL);
2192 } else if (!strcmp(command, "grep")) {
2193 xmlShellGrep(ctxt, arg, ctxt->node, NULL);
2194 } else if (!strcmp(command, "free")) {
2196 xmlMemShow(ctxt->output, 0);
2200 sscanf(arg, "%d", &len);
2201 xmlMemShow(ctxt->output, len);
2203 } else if (!strcmp(command, "pwd")) {
2206 if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
2207 fprintf(ctxt->output, "%s\n", dir);
2208 } else if (!strcmp(command, "du")) {
2209 xmlShellDu(ctxt, NULL, ctxt->node, NULL);
2210 } else if (!strcmp(command, "base")) {
2211 xmlShellBase(ctxt, NULL, ctxt->node, NULL);
2212 #ifdef LIBXML_XPATH_ENABLED
2213 } else if (!strcmp(command, "xpath")) {
2215 xmlGenericError(xmlGenericErrorContext,
2216 "xpath: expression required\n");
2218 ctxt->pctxt->node = ctxt->node;
2219 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2220 xmlXPathDebugDumpObject(ctxt->output, list, 0);
2221 xmlXPathFreeObject(list);
2223 #endif /* LIBXML_XPATH_ENABLED */
2224 } else if (!strcmp(command, "setbase")) {
2225 xmlShellSetBase(ctxt, arg, ctxt->node, NULL);
2226 } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) {
2227 int dir = (!strcmp(command, "dir"));
2231 xmlShellDir(ctxt, NULL, ctxt->node, NULL);
2233 xmlShellList(ctxt, NULL, ctxt->node, NULL);
2235 ctxt->pctxt->node = ctxt->node;
2236 #ifdef LIBXML_XPATH_ENABLED
2237 ctxt->pctxt->node = ctxt->node;
2238 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2241 #endif /* LIBXML_XPATH_ENABLED */
2243 switch (list->type) {
2244 case XPATH_UNDEFINED:
2245 xmlGenericError(xmlGenericErrorContext,
2246 "%s: no such node\n", arg);
2248 case XPATH_NODESET:{
2251 if (list->nodesetval == NULL)
2255 indx < list->nodesetval->nodeNr;
2258 xmlShellDir(ctxt, NULL,
2260 nodeTab[indx], NULL);
2262 xmlShellList(ctxt, NULL,
2264 nodeTab[indx], NULL);
2269 xmlGenericError(xmlGenericErrorContext,
2270 "%s is a Boolean\n", arg);
2273 xmlGenericError(xmlGenericErrorContext,
2274 "%s is a number\n", arg);
2277 xmlGenericError(xmlGenericErrorContext,
2278 "%s is a string\n", arg);
2281 xmlGenericError(xmlGenericErrorContext,
2282 "%s is a point\n", arg);
2285 xmlGenericError(xmlGenericErrorContext,
2286 "%s is a range\n", arg);
2288 case XPATH_LOCATIONSET:
2289 xmlGenericError(xmlGenericErrorContext,
2290 "%s is a range\n", arg);
2293 xmlGenericError(xmlGenericErrorContext,
2294 "%s is user-defined\n", arg);
2296 case XPATH_XSLT_TREE:
2297 xmlGenericError(xmlGenericErrorContext,
2298 "%s is an XSLT value tree\n",
2302 #ifdef LIBXML_XPATH_ENABLED
2303 xmlXPathFreeObject(list);
2306 xmlGenericError(xmlGenericErrorContext,
2307 "%s: no such node\n", arg);
2309 ctxt->pctxt->node = NULL;
2311 } else if (!strcmp(command, "cd")) {
2313 ctxt->node = (xmlNodePtr) ctxt->doc;
2315 #ifdef LIBXML_XPATH_ENABLED
2316 ctxt->pctxt->node = ctxt->node;
2317 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2320 #endif /* LIBXML_XPATH_ENABLED */
2322 switch (list->type) {
2323 case XPATH_UNDEFINED:
2324 xmlGenericError(xmlGenericErrorContext,
2325 "%s: no such node\n", arg);
2328 if (list->nodesetval != NULL) {
2329 if (list->nodesetval->nodeNr == 1) {
2330 ctxt->node = list->nodesetval->nodeTab[0];
2332 xmlGenericError(xmlGenericErrorContext,
2333 "%s is a %d Node Set\n",
2335 list->nodesetval->nodeNr);
2337 xmlGenericError(xmlGenericErrorContext,
2338 "%s is an empty Node Set\n",
2342 xmlGenericError(xmlGenericErrorContext,
2343 "%s is a Boolean\n", arg);
2346 xmlGenericError(xmlGenericErrorContext,
2347 "%s is a number\n", arg);
2350 xmlGenericError(xmlGenericErrorContext,
2351 "%s is a string\n", arg);
2354 xmlGenericError(xmlGenericErrorContext,
2355 "%s is a point\n", arg);
2358 xmlGenericError(xmlGenericErrorContext,
2359 "%s is a range\n", arg);
2361 case XPATH_LOCATIONSET:
2362 xmlGenericError(xmlGenericErrorContext,
2363 "%s is a range\n", arg);
2366 xmlGenericError(xmlGenericErrorContext,
2367 "%s is user-defined\n", arg);
2369 case XPATH_XSLT_TREE:
2370 xmlGenericError(xmlGenericErrorContext,
2371 "%s is an XSLT value tree\n",
2375 #ifdef LIBXML_XPATH_ENABLED
2376 xmlXPathFreeObject(list);
2379 xmlGenericError(xmlGenericErrorContext,
2380 "%s: no such node\n", arg);
2382 ctxt->pctxt->node = NULL;
2384 } else if (!strcmp(command, "cat")) {
2386 xmlShellCat(ctxt, NULL, ctxt->node, NULL);
2388 ctxt->pctxt->node = ctxt->node;
2389 #ifdef LIBXML_XPATH_ENABLED
2390 ctxt->pctxt->node = ctxt->node;
2391 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2394 #endif /* LIBXML_XPATH_ENABLED */
2396 switch (list->type) {
2397 case XPATH_UNDEFINED:
2398 xmlGenericError(xmlGenericErrorContext,
2399 "%s: no such node\n", arg);
2401 case XPATH_NODESET:{
2404 if (list->nodesetval == NULL)
2408 indx < list->nodesetval->nodeNr;
2411 fprintf(ctxt->output, " -------\n");
2412 xmlShellCat(ctxt, NULL,
2414 nodeTab[indx], NULL);
2419 xmlGenericError(xmlGenericErrorContext,
2420 "%s is a Boolean\n", arg);
2423 xmlGenericError(xmlGenericErrorContext,
2424 "%s is a number\n", arg);
2427 xmlGenericError(xmlGenericErrorContext,
2428 "%s is a string\n", arg);
2431 xmlGenericError(xmlGenericErrorContext,
2432 "%s is a point\n", arg);
2435 xmlGenericError(xmlGenericErrorContext,
2436 "%s is a range\n", arg);
2438 case XPATH_LOCATIONSET:
2439 xmlGenericError(xmlGenericErrorContext,
2440 "%s is a range\n", arg);
2443 xmlGenericError(xmlGenericErrorContext,
2444 "%s is user-defined\n", arg);
2446 case XPATH_XSLT_TREE:
2447 xmlGenericError(xmlGenericErrorContext,
2448 "%s is an XSLT value tree\n",
2452 #ifdef LIBXML_XPATH_ENABLED
2453 xmlXPathFreeObject(list);
2456 xmlGenericError(xmlGenericErrorContext,
2457 "%s: no such node\n", arg);
2459 ctxt->pctxt->node = NULL;
2462 xmlGenericError(xmlGenericErrorContext,
2463 "Unknown command %s\n", command);
2465 free(cmdline); /* not xmlFree here ! */
2467 #ifdef LIBXML_XPATH_ENABLED
2468 xmlXPathFreeContext(ctxt->pctxt);
2469 #endif /* LIBXML_XPATH_ENABLED */
2471 xmlFreeDoc(ctxt->doc);
2473 if (ctxt->filename != NULL)
2474 xmlFree(ctxt->filename);
2476 if (cmdline != NULL)
2477 free(cmdline); /* not xmlFree here ! */
2480 #endif /* LIBXML_DEBUG_ENABLED */