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>
32 #include <libxml/uri.h>
36 * @output: the FILE * for the output
39 * Dumps informations about the string, shorten it if necessary
42 xmlDebugDumpString(FILE * output, const xmlChar * str)
49 fprintf(output, "(NULL)");
52 for (i = 0; i < 40; i++)
55 else if (IS_BLANK(str[i]))
57 else if (str[i] >= 0x80)
58 fprintf(output, "#%X", str[i]);
60 fputc(str[i], output);
61 fprintf(output, "...");
65 xmlDebugDumpDtdNode(FILE *output, xmlDtdPtr dtd, int depth) {
69 for (i = 0;((i < depth) && (i < 25));i++)
70 shift[2 * i] = shift[2 * i + 1] = ' ';
71 shift[2 * i] = shift[2 * i + 1] = 0;
73 fprintf(output, shift);
76 fprintf(output, "DTD node is NULL\n");
80 if (dtd->type != XML_DTD_NODE) {
81 fprintf(output, "PBM: not a DTD\n");
84 if (dtd->name != NULL)
85 fprintf(output, "DTD(%s)", dtd->name);
87 fprintf(output, "DTD");
88 if (dtd->ExternalID != NULL)
89 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
90 if (dtd->SystemID != NULL)
91 fprintf(output, ", SYSTEM %s", dtd->SystemID);
92 fprintf(output, "\n");
94 * Do a bit of checking
96 if (dtd->parent == NULL)
97 fprintf(output, "PBM: DTD has no parent\n");
99 fprintf(output, "PBM: DTD has no doc\n");
100 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
101 fprintf(output, "PBM: DTD doc differs from parent's one\n");
102 if (dtd->prev == NULL) {
103 if ((dtd->parent != NULL) && (dtd->parent->children != (xmlNodePtr)dtd))
104 fprintf(output, "PBM: DTD has no prev and not first of list\n");
106 if (dtd->prev->next != (xmlNodePtr) dtd)
107 fprintf(output, "PBM: DTD prev->next : back link wrong\n");
109 if (dtd->next == NULL) {
110 if ((dtd->parent != NULL) && (dtd->parent->last != (xmlNodePtr) dtd))
111 fprintf(output, "PBM: DTD has no next and not last of list\n");
113 if (dtd->next->prev != (xmlNodePtr) dtd)
114 fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
119 xmlDebugDumpAttrDecl(FILE *output, xmlAttributePtr attr, int depth) {
123 for (i = 0;((i < depth) && (i < 25));i++)
124 shift[2 * i] = shift[2 * i + 1] = ' ';
125 shift[2 * i] = shift[2 * i + 1] = 0;
127 fprintf(output, shift);
130 fprintf(output, "Attribute declaration is NULL\n");
133 if (attr->type != XML_ATTRIBUTE_DECL) {
134 fprintf(output, "PBM: not a Attr\n");
137 if (attr->name != NULL)
138 fprintf(output, "ATTRDECL(%s)", attr->name);
140 fprintf(output, "PBM ATTRDECL noname!!!");
141 if (attr->elem != NULL)
142 fprintf(output, " for %s", attr->elem);
144 fprintf(output, " PBM noelem!!!");
145 switch (attr->atype) {
146 case XML_ATTRIBUTE_CDATA:
147 fprintf(output, " CDATA");
149 case XML_ATTRIBUTE_ID:
150 fprintf(output, " ID");
152 case XML_ATTRIBUTE_IDREF:
153 fprintf(output, " IDREF");
155 case XML_ATTRIBUTE_IDREFS:
156 fprintf(output, " IDREFS");
158 case XML_ATTRIBUTE_ENTITY:
159 fprintf(output, " ENTITY");
161 case XML_ATTRIBUTE_ENTITIES:
162 fprintf(output, " ENTITIES");
164 case XML_ATTRIBUTE_NMTOKEN:
165 fprintf(output, " NMTOKEN");
167 case XML_ATTRIBUTE_NMTOKENS:
168 fprintf(output, " NMTOKENS");
170 case XML_ATTRIBUTE_ENUMERATION:
171 fprintf(output, " ENUMERATION");
173 case XML_ATTRIBUTE_NOTATION:
174 fprintf(output, " NOTATION ");
177 if (attr->tree != NULL) {
179 xmlEnumerationPtr cur = attr->tree;
181 for (indx = 0;indx < 5; indx++) {
183 fprintf(output, "|%s", cur->name);
185 fprintf(output, " (%s", cur->name);
187 if (cur == NULL) break;
190 fprintf(output, ")");
192 fprintf(output, "...)");
195 case XML_ATTRIBUTE_NONE:
197 case XML_ATTRIBUTE_REQUIRED:
198 fprintf(output, " REQUIRED");
200 case XML_ATTRIBUTE_IMPLIED:
201 fprintf(output, " IMPLIED");
203 case XML_ATTRIBUTE_FIXED:
204 fprintf(output, " FIXED");
207 if (attr->defaultValue != NULL) {
208 fprintf(output, "\"");
209 xmlDebugDumpString(output, attr->defaultValue);
210 fprintf(output, "\"");
212 fprintf(output, "\n");
215 * Do a bit of checking
217 if (attr->parent == NULL)
218 fprintf(output, "PBM: Attr has no parent\n");
219 if (attr->doc == NULL)
220 fprintf(output, "PBM: Attr has no doc\n");
221 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
222 fprintf(output, "PBM: Attr doc differs from parent's one\n");
223 if (attr->prev == NULL) {
224 if ((attr->parent != NULL) && (attr->parent->children != (xmlNodePtr)attr))
225 fprintf(output, "PBM: Attr has no prev and not first of list\n");
227 if (attr->prev->next != (xmlNodePtr) attr)
228 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
230 if (attr->next == NULL) {
231 if ((attr->parent != NULL) && (attr->parent->last != (xmlNodePtr) attr))
232 fprintf(output, "PBM: Attr has no next and not last of list\n");
234 if (attr->next->prev != (xmlNodePtr) attr)
235 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
240 xmlDebugDumpElemDecl(FILE *output, xmlElementPtr elem, int depth) {
244 for (i = 0;((i < depth) && (i < 25));i++)
245 shift[2 * i] = shift[2 * i + 1] = ' ';
246 shift[2 * i] = shift[2 * i + 1] = 0;
248 fprintf(output, shift);
251 fprintf(output, "Element declaration is NULL\n");
254 if (elem->type != XML_ELEMENT_DECL) {
255 fprintf(output, "PBM: not a Elem\n");
258 if (elem->name != NULL) {
259 fprintf(output, "ELEMDECL(");
260 xmlDebugDumpString(output, elem->name);
261 fprintf(output, ")");
263 fprintf(output, "PBM ELEMDECL noname!!!");
264 switch (elem->etype) {
265 case XML_ELEMENT_TYPE_UNDEFINED:
266 fprintf(output, ", UNDEFINED");
268 case XML_ELEMENT_TYPE_EMPTY:
269 fprintf(output, ", EMPTY");
271 case XML_ELEMENT_TYPE_ANY:
272 fprintf(output, ", ANY");
274 case XML_ELEMENT_TYPE_MIXED:
275 fprintf(output, ", MIXED ");
277 case XML_ELEMENT_TYPE_ELEMENT:
278 fprintf(output, ", MIXED ");
281 if ((elem->type != XML_ELEMENT_NODE) &&
282 (elem->content != NULL)) {
286 xmlSnprintfElementContent(buf, 5000, elem->content, 1);
288 fprintf(output, "%s", buf);
290 fprintf(output, "\n");
293 * Do a bit of checking
295 if (elem->parent == NULL)
296 fprintf(output, "PBM: Elem has no parent\n");
297 if (elem->doc == NULL)
298 fprintf(output, "PBM: Elem has no doc\n");
299 if ((elem->parent != NULL) && (elem->doc != elem->parent->doc))
300 fprintf(output, "PBM: Elem doc differs from parent's one\n");
301 if (elem->prev == NULL) {
302 if ((elem->parent != NULL) && (elem->parent->children != (xmlNodePtr)elem))
303 fprintf(output, "PBM: Elem has no prev and not first of list\n");
305 if (elem->prev->next != (xmlNodePtr) elem)
306 fprintf(output, "PBM: Elem prev->next : back link wrong\n");
308 if (elem->next == NULL) {
309 if ((elem->parent != NULL) && (elem->parent->last != (xmlNodePtr) elem))
310 fprintf(output, "PBM: Elem has no next and not last of list\n");
312 if (elem->next->prev != (xmlNodePtr) elem)
313 fprintf(output, "PBM: Elem next->prev : forward link wrong\n");
318 xmlDebugDumpEntityDecl(FILE *output, xmlEntityPtr ent, int depth) {
322 for (i = 0;((i < depth) && (i < 25));i++)
323 shift[2 * i] = shift[2 * i + 1] = ' ';
324 shift[2 * i] = shift[2 * i + 1] = 0;
326 fprintf(output, shift);
329 fprintf(output, "Entity declaration is NULL\n");
332 if (ent->type != XML_ENTITY_DECL) {
333 fprintf(output, "PBM: not a Entity decl\n");
336 if (ent->name != NULL) {
337 fprintf(output, "ENTITYDECL(");
338 xmlDebugDumpString(output, ent->name);
339 fprintf(output, ")");
341 fprintf(output, "PBM ENTITYDECL noname!!!");
342 switch (ent->etype) {
343 case XML_INTERNAL_GENERAL_ENTITY:
344 fprintf(output, ", internal\n");
346 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
347 fprintf(output, ", external parsed\n");
349 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
350 fprintf(output, ", unparsed\n");
352 case XML_INTERNAL_PARAMETER_ENTITY:
353 fprintf(output, ", parameter\n");
355 case XML_EXTERNAL_PARAMETER_ENTITY:
356 fprintf(output, ", external parameter\n");
358 case XML_INTERNAL_PREDEFINED_ENTITY:
359 fprintf(output, ", predefined\n");
362 if (ent->ExternalID) {
363 fprintf(output, shift);
364 fprintf(output, " ExternalID=%s\n", ent->ExternalID);
367 fprintf(output, shift);
368 fprintf(output, " SystemID=%s\n", ent->SystemID);
370 if (ent->URI != NULL) {
371 fprintf(output, shift);
372 fprintf(output, " URI=%s\n", ent->URI);
375 fprintf(output, shift);
376 fprintf(output, " content=");
377 xmlDebugDumpString(output, ent->content);
378 fprintf(output, "\n");
382 * Do a bit of checking
384 if (ent->parent == NULL)
385 fprintf(output, "PBM: Ent has no parent\n");
386 if (ent->doc == NULL)
387 fprintf(output, "PBM: Ent has no doc\n");
388 if ((ent->parent != NULL) && (ent->doc != ent->parent->doc))
389 fprintf(output, "PBM: Ent doc differs from parent's one\n");
390 if (ent->prev == NULL) {
391 if ((ent->parent != NULL) && (ent->parent->children != (xmlNodePtr)ent))
392 fprintf(output, "PBM: Ent has no prev and not first of list\n");
394 if (ent->prev->next != (xmlNodePtr) ent)
395 fprintf(output, "PBM: Ent prev->next : back link wrong\n");
397 if (ent->next == NULL) {
398 if ((ent->parent != NULL) && (ent->parent->last != (xmlNodePtr) ent))
399 fprintf(output, "PBM: Ent has no next and not last of list\n");
401 if (ent->next->prev != (xmlNodePtr) ent)
402 fprintf(output, "PBM: Ent next->prev : forward link wrong\n");
407 xmlDebugDumpNamespace(FILE *output, xmlNsPtr ns, int depth) {
411 for (i = 0;((i < depth) && (i < 25));i++)
412 shift[2 * i] = shift[2 * i + 1] = ' ';
413 shift[2 * i] = shift[2 * i + 1] = 0;
415 fprintf(output, shift);
418 fprintf(output, "namespace node is NULL\n");
421 if (ns->type != XML_NAMESPACE_DECL) {
422 fprintf(output, "invalid namespace node %d\n", ns->type);
425 if (ns->href == NULL) {
426 if (ns->prefix != NULL)
427 fprintf(output, "incomplete namespace %s href=NULL\n", ns->prefix);
429 fprintf(output, "incomplete default namespace href=NULL\n");
431 if (ns->prefix != NULL)
432 fprintf(output, "namespace %s href=", ns->prefix);
434 fprintf(output, "default namespace href=");
436 xmlDebugDumpString(output, ns->href);
437 fprintf(output, "\n");
442 xmlDebugDumpNamespaceList(FILE *output, xmlNsPtr ns, int depth) {
444 xmlDebugDumpNamespace(output, ns, depth);
450 xmlDebugDumpEntity(FILE *output, xmlEntityPtr ent, int depth) {
454 for (i = 0;((i < depth) && (i < 25));i++)
455 shift[2 * i] = shift[2 * i + 1] = ' ';
456 shift[2 * i] = shift[2 * i + 1] = 0;
458 fprintf(output, shift);
461 fprintf(output, "Entity is NULL\n");
464 switch (ent->etype) {
465 case XML_INTERNAL_GENERAL_ENTITY:
466 fprintf(output, "INTERNAL_GENERAL_ENTITY ");
468 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
469 fprintf(output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
471 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
472 fprintf(output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
474 case XML_INTERNAL_PARAMETER_ENTITY:
475 fprintf(output, "INTERNAL_PARAMETER_ENTITY ");
477 case XML_EXTERNAL_PARAMETER_ENTITY:
478 fprintf(output, "EXTERNAL_PARAMETER_ENTITY ");
481 fprintf(output, "ENTITY_%d ! ", ent->etype);
483 fprintf(output, "%s\n", ent->name);
484 if (ent->ExternalID) {
485 fprintf(output, shift);
486 fprintf(output, "ExternalID=%s\n", ent->ExternalID);
489 fprintf(output, shift);
490 fprintf(output, "SystemID=%s\n", ent->SystemID);
493 fprintf(output, shift);
494 fprintf(output, "URI=%s\n", ent->URI);
497 fprintf(output, shift);
498 fprintf(output, "content=");
499 xmlDebugDumpString(output, ent->content);
500 fprintf(output, "\n");
506 * @output: the FILE * for the output
507 * @attr: the attribute
508 * @depth: the indentation level.
510 * Dumps debug information for the attribute
513 xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
517 for (i = 0;((i < depth) && (i < 25));i++)
518 shift[2 * i] = shift[2 * i + 1] = ' ';
519 shift[2 * i] = shift[2 * i + 1] = 0;
521 fprintf(output, shift);
524 fprintf(output, "Attr is NULL");
527 fprintf(output, "ATTRIBUTE ");
528 xmlDebugDumpString(output, attr->name);
529 fprintf(output, "\n");
530 if (attr->children != NULL)
531 xmlDebugDumpNodeList(output, attr->children, depth + 1);
534 * Do a bit of checking
536 if (attr->parent == NULL)
537 fprintf(output, "PBM: Attr has no parent\n");
538 if (attr->doc == NULL)
539 fprintf(output, "PBM: Attr has no doc\n");
540 if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
541 fprintf(output, "PBM: Attr doc differs from parent's one\n");
542 if (attr->prev == NULL) {
543 if ((attr->parent != NULL) && (attr->parent->properties != attr))
544 fprintf(output, "PBM: Attr has no prev and not first of list\n");
546 if (attr->prev->next != attr)
547 fprintf(output, "PBM: Attr prev->next : back link wrong\n");
549 if (attr->next != NULL) {
550 if (attr->next->prev != attr)
551 fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
556 * xmlDebugDumpAttrList:
557 * @output: the FILE * for the output
558 * @attr: the attribute list
559 * @depth: the indentation level.
561 * Dumps debug information for the attribute list
564 xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth)
568 while (attr != NULL) {
569 xmlDebugDumpAttr(output, attr, depth);
575 * xmlDebugDumpOneNode:
576 * @output: the FILE * for the output
578 * @depth: the indentation level.
580 * Dumps debug information for the element node, it is not recursive
583 xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth)
590 for (i = 0; ((i < depth) && (i < 25)); i++)
591 shift[2 * i] = shift[2 * i + 1] = ' ';
592 shift[2 * i] = shift[2 * i + 1] = 0;
595 fprintf(output, shift);
596 fprintf(output, "node is NULL\n");
599 switch (node->type) {
600 case XML_ELEMENT_NODE:
601 fprintf(output, shift);
602 fprintf(output, "ELEMENT ");
603 if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
604 xmlDebugDumpString(output, node->ns->prefix);
605 fprintf(output, ":");
607 xmlDebugDumpString(output, node->name);
608 fprintf(output, "\n");
610 case XML_ATTRIBUTE_NODE:
611 fprintf(output, shift);
612 fprintf(output, "Error, ATTRIBUTE found here\n");
615 fprintf(output, shift);
616 if (node->name == (const xmlChar *) xmlStringTextNoenc)
617 fprintf(output, "TEXT no enc\n");
619 fprintf(output, "TEXT\n");
621 case XML_CDATA_SECTION_NODE:
622 fprintf(output, shift);
623 fprintf(output, "CDATA_SECTION\n");
625 case XML_ENTITY_REF_NODE:
626 fprintf(output, shift);
627 fprintf(output, "ENTITY_REF(%s)\n", node->name);
629 case XML_ENTITY_NODE:
630 fprintf(output, shift);
631 fprintf(output, "ENTITY\n");
634 fprintf(output, shift);
635 fprintf(output, "PI %s\n", node->name);
637 case XML_COMMENT_NODE:
638 fprintf(output, shift);
639 fprintf(output, "COMMENT\n");
641 case XML_DOCUMENT_NODE:
642 case XML_HTML_DOCUMENT_NODE:
643 fprintf(output, shift);
644 fprintf(output, "Error, DOCUMENT found here\n");
646 case XML_DOCUMENT_TYPE_NODE:
647 fprintf(output, shift);
648 fprintf(output, "DOCUMENT_TYPE\n");
650 case XML_DOCUMENT_FRAG_NODE:
651 fprintf(output, shift);
652 fprintf(output, "DOCUMENT_FRAG\n");
654 case XML_NOTATION_NODE:
655 fprintf(output, shift);
656 fprintf(output, "NOTATION\n");
659 xmlDebugDumpDtdNode(output, (xmlDtdPtr) node, depth);
661 case XML_ELEMENT_DECL:
662 xmlDebugDumpElemDecl(output, (xmlElementPtr) node, depth);
664 case XML_ATTRIBUTE_DECL:
665 xmlDebugDumpAttrDecl(output, (xmlAttributePtr) node, depth);
667 case XML_ENTITY_DECL:
668 xmlDebugDumpEntityDecl(output, (xmlEntityPtr) node, depth);
670 case XML_NAMESPACE_DECL:
671 xmlDebugDumpNamespace(output, (xmlNsPtr) node, depth);
673 case XML_XINCLUDE_START:
674 fprintf(output, shift);
675 fprintf(output, "INCLUDE START\n");
677 case XML_XINCLUDE_END:
678 fprintf(output, shift);
679 fprintf(output, "INCLUDE END\n");
682 fprintf(output, shift);
683 fprintf(output, "NODE_%d !!!\n", node->type);
686 if (node->doc == NULL) {
687 fprintf(output, shift);
688 fprintf(output, "doc == NULL !!!\n");
690 if (node->nsDef != NULL)
691 xmlDebugDumpNamespaceList(output, node->nsDef, depth + 1);
692 if (node->properties != NULL)
693 xmlDebugDumpAttrList(output, node->properties, depth + 1);
694 if (node->type != XML_ENTITY_REF_NODE) {
695 if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
696 shift[2 * i] = shift[2 * i + 1] = ' ';
697 shift[2 * i + 2] = shift[2 * i + 3] = 0;
698 fprintf(output, shift);
699 fprintf(output, "content=");
700 xmlDebugDumpString(output, node->content);
701 fprintf(output, "\n");
706 ent = xmlGetDocEntity(node->doc, node->name);
708 xmlDebugDumpEntity(output, ent, depth + 1);
711 * Do a bit of checking
713 if (node->parent == NULL)
714 fprintf(output, "PBM: Node has no parent\n");
715 if (node->doc == NULL)
716 fprintf(output, "PBM: Node has no doc\n");
717 if ((node->parent != NULL) && (node->doc != node->parent->doc))
718 fprintf(output, "PBM: Node doc differs from parent's one\n");
719 if (node->prev == NULL) {
720 if ((node->parent != NULL) && (node->parent->children != node))
722 "PBM: Node has no prev and not first of list\n");
724 if (node->prev->next != node)
725 fprintf(output, "PBM: Node prev->next : back link wrong\n");
727 if (node->next == NULL) {
728 if ((node->parent != NULL) && (node->parent->last != node))
730 "PBM: Node has no next and not last of list\n");
732 if (node->next->prev != node)
733 fprintf(output, "PBM: Node next->prev : forward link wrong\n");
739 * @output: the FILE * for the output
741 * @depth: the indentation level.
743 * Dumps debug information for the element node, it is recursive
746 xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth)
754 for (i = 0; ((i < depth) && (i < 25)); i++)
755 shift[2 * i] = shift[2 * i + 1] = ' ';
756 shift[2 * i] = shift[2 * i + 1] = 0;
758 fprintf(output, shift);
759 fprintf(output, "node is NULL\n");
762 xmlDebugDumpOneNode(output, node, depth);
763 if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE))
764 xmlDebugDumpNodeList(output, node->children, depth + 1);
768 * xmlDebugDumpNodeList:
769 * @output: the FILE * for the output
770 * @node: the node list
771 * @depth: the indentation level.
773 * Dumps debug information for the list of element node, it is recursive
776 xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth)
780 while (node != NULL) {
781 xmlDebugDumpNode(output, node, depth);
788 * xmlDebugDumpDocumentHead:
789 * @output: the FILE * for the output
792 * Dumps debug information cncerning the document, not recursive
795 xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc)
800 fprintf(output, "DOCUMENT == NULL !\n");
805 case XML_ELEMENT_NODE:
806 fprintf(output, "Error, ELEMENT found here ");
808 case XML_ATTRIBUTE_NODE:
809 fprintf(output, "Error, ATTRIBUTE found here\n");
812 fprintf(output, "Error, TEXT\n");
814 case XML_CDATA_SECTION_NODE:
815 fprintf(output, "Error, CDATA_SECTION\n");
817 case XML_ENTITY_REF_NODE:
818 fprintf(output, "Error, ENTITY_REF\n");
820 case XML_ENTITY_NODE:
821 fprintf(output, "Error, ENTITY\n");
824 fprintf(output, "Error, PI\n");
826 case XML_COMMENT_NODE:
827 fprintf(output, "Error, COMMENT\n");
829 case XML_DOCUMENT_NODE:
830 fprintf(output, "DOCUMENT\n");
832 case XML_HTML_DOCUMENT_NODE:
833 fprintf(output, "HTML DOCUMENT\n");
835 case XML_DOCUMENT_TYPE_NODE:
836 fprintf(output, "Error, DOCUMENT_TYPE\n");
838 case XML_DOCUMENT_FRAG_NODE:
839 fprintf(output, "Error, DOCUMENT_FRAG\n");
841 case XML_NOTATION_NODE:
842 fprintf(output, "Error, NOTATION\n");
845 fprintf(output, "NODE_%d\n", doc->type);
847 if (doc->name != NULL) {
848 fprintf(output, "name=");
849 xmlDebugDumpString(output, BAD_CAST doc->name);
850 fprintf(output, "\n");
852 if (doc->version != NULL) {
853 fprintf(output, "version=");
854 xmlDebugDumpString(output, doc->version);
855 fprintf(output, "\n");
857 if (doc->encoding != NULL) {
858 fprintf(output, "encoding=");
859 xmlDebugDumpString(output, doc->encoding);
860 fprintf(output, "\n");
862 if (doc->URL != NULL) {
863 fprintf(output, "URL=");
864 xmlDebugDumpString(output, doc->URL);
865 fprintf(output, "\n");
868 fprintf(output, "standalone=true\n");
869 if (doc->oldNs != NULL)
870 xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
874 * xmlDebugDumpDocument:
875 * @output: the FILE * for the output
878 * Dumps debug information for the document, it's recursive
881 xmlDebugDumpDocument(FILE * output, xmlDocPtr doc)
886 fprintf(output, "DOCUMENT == NULL !\n");
889 xmlDebugDumpDocumentHead(output, doc);
890 if (((doc->type == XML_DOCUMENT_NODE) ||
891 (doc->type == XML_HTML_DOCUMENT_NODE)) && (doc->children != NULL))
892 xmlDebugDumpNodeList(output, doc->children, 1);
897 * @output: the FILE * for the output
900 * Dumps debug information for the DTD
903 xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd)
908 fprintf(output, "DTD is NULL\n");
911 if (dtd->type != XML_DTD_NODE) {
912 fprintf(output, "PBM: not a DTD\n");
915 if (dtd->name != NULL)
916 fprintf(output, "DTD(%s)", dtd->name);
918 fprintf(output, "DTD");
919 if (dtd->ExternalID != NULL)
920 fprintf(output, ", PUBLIC %s", dtd->ExternalID);
921 if (dtd->SystemID != NULL)
922 fprintf(output, ", SYSTEM %s", dtd->SystemID);
923 fprintf(output, "\n");
925 * Do a bit of checking
927 if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
928 fprintf(output, "PBM: DTD doc differs from parent's one\n");
929 if (dtd->prev == NULL) {
930 if ((dtd->parent != NULL)
931 && (dtd->parent->children != (xmlNodePtr) dtd))
933 "PBM: DTD has no prev and not first of list\n");
935 if (dtd->prev->next != (xmlNodePtr) dtd)
936 fprintf(output, "PBM: DTD prev->next : back link wrong\n");
938 if (dtd->next == NULL) {
939 if ((dtd->parent != NULL)
940 && (dtd->parent->last != (xmlNodePtr) dtd))
941 fprintf(output, "PBM: DTD has no next and not last of list\n");
943 if (dtd->next->prev != (xmlNodePtr) dtd)
944 fprintf(output, "PBM: DTD next->prev : forward link wrong\n");
946 if (dtd->children == NULL)
947 fprintf(output, " DTD is empty\n");
949 xmlDebugDumpNodeList(output, dtd->children, 1);
953 xmlDebugDumpEntityCallback(xmlEntityPtr cur, FILE *output) {
955 fprintf(output, "Entity is NULL");
958 fprintf(output, "%s : ", cur->name);
959 switch (cur->etype) {
960 case XML_INTERNAL_GENERAL_ENTITY:
961 fprintf(output, "INTERNAL GENERAL, ");
963 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
964 fprintf(output, "EXTERNAL PARSED, ");
966 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
967 fprintf(output, "EXTERNAL UNPARSED, ");
969 case XML_INTERNAL_PARAMETER_ENTITY:
970 fprintf(output, "INTERNAL PARAMETER, ");
972 case XML_EXTERNAL_PARAMETER_ENTITY:
973 fprintf(output, "EXTERNAL PARAMETER, ");
976 fprintf(output, "UNKNOWN TYPE %d",
979 if (cur->ExternalID != NULL)
980 fprintf(output, "ID \"%s\"", cur->ExternalID);
981 if (cur->SystemID != NULL)
982 fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
983 if (cur->orig != NULL)
984 fprintf(output, "\n orig \"%s\"", cur->orig);
985 if ((cur->type != XML_ELEMENT_NODE) &&
986 (cur->content != NULL))
987 fprintf(output, "\n content \"%s\"", cur->content);
988 fprintf(output, "\n");
992 * xmlDebugDumpEntities:
993 * @output: the FILE * for the output
996 * Dumps debug information for all the entities in use by the document
999 xmlDebugDumpEntities(FILE * output, xmlDocPtr doc)
1004 fprintf(output, "DOCUMENT == NULL !\n");
1008 switch (doc->type) {
1009 case XML_ELEMENT_NODE:
1010 fprintf(output, "Error, ELEMENT found here ");
1012 case XML_ATTRIBUTE_NODE:
1013 fprintf(output, "Error, ATTRIBUTE found here\n");
1016 fprintf(output, "Error, TEXT\n");
1018 case XML_CDATA_SECTION_NODE:
1019 fprintf(output, "Error, CDATA_SECTION\n");
1021 case XML_ENTITY_REF_NODE:
1022 fprintf(output, "Error, ENTITY_REF\n");
1024 case XML_ENTITY_NODE:
1025 fprintf(output, "Error, ENTITY\n");
1028 fprintf(output, "Error, PI\n");
1030 case XML_COMMENT_NODE:
1031 fprintf(output, "Error, COMMENT\n");
1033 case XML_DOCUMENT_NODE:
1034 fprintf(output, "DOCUMENT\n");
1036 case XML_HTML_DOCUMENT_NODE:
1037 fprintf(output, "HTML DOCUMENT\n");
1039 case XML_DOCUMENT_TYPE_NODE:
1040 fprintf(output, "Error, DOCUMENT_TYPE\n");
1042 case XML_DOCUMENT_FRAG_NODE:
1043 fprintf(output, "Error, DOCUMENT_FRAG\n");
1045 case XML_NOTATION_NODE:
1046 fprintf(output, "Error, NOTATION\n");
1049 fprintf(output, "NODE_%d\n", doc->type);
1051 if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
1052 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1053 doc->intSubset->entities;
1055 fprintf(output, "Entities in internal subset\n");
1056 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1059 fprintf(output, "No entities in internal subset\n");
1060 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
1061 xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
1062 doc->extSubset->entities;
1064 fprintf(output, "Entities in external subset\n");
1065 xmlHashScan(table, (xmlHashScanner) xmlDebugDumpEntityCallback,
1068 fprintf(output, "No entities in external subset\n");
1073 * @node: the node to count
1075 * Count the children of @node.
1077 * Returns the number of children of @node.
1080 xmlLsCountNode(xmlNodePtr node) {
1082 xmlNodePtr list = NULL;
1087 switch (node->type) {
1088 case XML_ELEMENT_NODE:
1089 list = node->children;
1091 case XML_DOCUMENT_NODE:
1092 case XML_HTML_DOCUMENT_NODE:
1093 #ifdef LIBXML_DOCB_ENABLED
1094 case XML_DOCB_DOCUMENT_NODE:
1096 list = ((xmlDocPtr) node)->children;
1098 case XML_ATTRIBUTE_NODE:
1099 list = ((xmlAttrPtr) node)->children;
1102 case XML_CDATA_SECTION_NODE:
1104 case XML_COMMENT_NODE:
1105 if (node->content != NULL) {
1106 ret = xmlStrlen(node->content);
1109 case XML_ENTITY_REF_NODE:
1110 case XML_DOCUMENT_TYPE_NODE:
1111 case XML_ENTITY_NODE:
1112 case XML_DOCUMENT_FRAG_NODE:
1113 case XML_NOTATION_NODE:
1115 case XML_ELEMENT_DECL:
1116 case XML_ATTRIBUTE_DECL:
1117 case XML_ENTITY_DECL:
1118 case XML_NAMESPACE_DECL:
1119 case XML_XINCLUDE_START:
1120 case XML_XINCLUDE_END:
1124 for (;list != NULL;ret++)
1131 * @output: the FILE * for the output
1132 * @node: the node to dump
1134 * Dump to @output the type and name of @node.
1137 xmlLsOneNode(FILE *output, xmlNodePtr node) {
1139 fprintf(output, "NULL\n");
1142 switch (node->type) {
1143 case XML_ELEMENT_NODE:
1144 fprintf(output, "-");
1146 case XML_ATTRIBUTE_NODE:
1147 fprintf(output, "a");
1150 fprintf(output, "t");
1152 case XML_CDATA_SECTION_NODE:
1153 fprintf(output, "C");
1155 case XML_ENTITY_REF_NODE:
1156 fprintf(output, "e");
1158 case XML_ENTITY_NODE:
1159 fprintf(output, "E");
1162 fprintf(output, "p");
1164 case XML_COMMENT_NODE:
1165 fprintf(output, "c");
1167 case XML_DOCUMENT_NODE:
1168 fprintf(output, "d");
1170 case XML_HTML_DOCUMENT_NODE:
1171 fprintf(output, "h");
1173 case XML_DOCUMENT_TYPE_NODE:
1174 fprintf(output, "T");
1176 case XML_DOCUMENT_FRAG_NODE:
1177 fprintf(output, "F");
1179 case XML_NOTATION_NODE:
1180 fprintf(output, "N");
1182 case XML_NAMESPACE_DECL:
1183 fprintf(output, "n");
1186 fprintf(output, "?");
1188 if (node->type != XML_NAMESPACE_DECL) {
1189 if (node->properties != NULL)
1190 fprintf(output, "a");
1192 fprintf(output, "-");
1193 if (node->nsDef != NULL)
1194 fprintf(output, "n");
1196 fprintf(output, "-");
1199 fprintf(output, " %8d ", xmlLsCountNode(node));
1201 switch (node->type) {
1202 case XML_ELEMENT_NODE:
1203 if (node->name != NULL)
1204 fprintf(output, "%s", (const char *) node->name);
1206 case XML_ATTRIBUTE_NODE:
1207 if (node->name != NULL)
1208 fprintf(output, "%s", (const char *) node->name);
1211 if (node->content != NULL) {
1212 xmlDebugDumpString(output, node->content);
1215 case XML_CDATA_SECTION_NODE:
1217 case XML_ENTITY_REF_NODE:
1218 if (node->name != NULL)
1219 fprintf(output, "%s", (const char *) node->name);
1221 case XML_ENTITY_NODE:
1222 if (node->name != NULL)
1223 fprintf(output, "%s", (const char *) node->name);
1226 if (node->name != NULL)
1227 fprintf(output, "%s", (const char *) node->name);
1229 case XML_COMMENT_NODE:
1231 case XML_DOCUMENT_NODE:
1233 case XML_HTML_DOCUMENT_NODE:
1235 case XML_DOCUMENT_TYPE_NODE:
1237 case XML_DOCUMENT_FRAG_NODE:
1239 case XML_NOTATION_NODE:
1241 case XML_NAMESPACE_DECL: {
1242 xmlNsPtr ns = (xmlNsPtr) node;
1244 if (ns->prefix == NULL)
1245 fprintf(output, "default -> %s", ns->href);
1247 fprintf(output, "%s -> %s", ns->prefix, ns->href);
1251 if (node->name != NULL)
1252 fprintf(output, "%s", (const char *) node->name);
1254 fprintf(output, "\n");
1259 * @boolval: a bool to turn into text
1261 * Convenient way to turn bool into text
1263 * Returns a pointer to either "True" or "False"
1266 xmlBoolToText(int boolval)
1274 /****************************************************************
1276 * The XML shell related functions *
1278 ****************************************************************/
1283 * TODO: Improvement/cleanups for the XML shell
1284 * - allow to shell out an editor on a subpart
1285 * - cleanup function registrations (with help) and calling
1286 * - provide registration routines
1290 * xmlShellPrintXPathError:
1291 * @errorType: valid xpath error id
1292 * @arg: the argument that cause xpath to fail
1294 * Print the xpath error to libxml default error channel
1297 xmlShellPrintXPathError(int errorType, const char *arg)
1299 const char *default_arg = "Result";
1304 switch (errorType) {
1305 case XPATH_UNDEFINED:
1306 xmlGenericError(xmlGenericErrorContext,
1307 "%s: no such node\n", arg);
1311 xmlGenericError(xmlGenericErrorContext,
1312 "%s is a Boolean\n", arg);
1315 xmlGenericError(xmlGenericErrorContext,
1316 "%s is a number\n", arg);
1319 xmlGenericError(xmlGenericErrorContext,
1320 "%s is a string\n", arg);
1323 xmlGenericError(xmlGenericErrorContext,
1324 "%s is a point\n", arg);
1327 xmlGenericError(xmlGenericErrorContext,
1328 "%s is a range\n", arg);
1330 case XPATH_LOCATIONSET:
1331 xmlGenericError(xmlGenericErrorContext,
1332 "%s is a range\n", arg);
1335 xmlGenericError(xmlGenericErrorContext,
1336 "%s is user-defined\n", arg);
1338 case XPATH_XSLT_TREE:
1339 xmlGenericError(xmlGenericErrorContext,
1340 "%s is an XSLT value tree\n", arg);
1343 xmlGenericError(xmlGenericErrorContext,
1344 "Try casting the result string function (xpath builtin)\n",
1350 * xmlShellPrintNodeCtxt:
1351 * @ctxt : a non-null shell context
1352 * @node : a non-null node to print to the output FILE
1354 * Print node to the output FILE
1357 xmlShellPrintNodeCtxt(xmlShellCtxtPtr ctxt,xmlNodePtr node)
1368 if (node->type == XML_DOCUMENT_NODE)
1369 xmlDocDump(fp, (xmlDocPtr) node);
1370 else if (node->type == XML_ATTRIBUTE_NODE)
1371 xmlDebugDumpAttrList(fp, (xmlAttrPtr) node, 0);
1373 xmlElemDump(fp, node->doc, node);
1379 * xmlShellPrintNode:
1380 * @node : a non-null node to print to the output FILE
1382 * Print node to the output FILE
1385 xmlShellPrintNode(xmlNodePtr node)
1387 xmlShellPrintNodeCtxt(NULL, node);
1391 * xmlShellPrintXPathResultCtxt:
1392 * @ctxt: a valid shell context
1393 * @list: a valid result generated by an xpath evaluation
1395 * Prints result to the output FILE
1398 xmlShellPrintXPathResultCtxt(xmlShellCtxtPtr ctxt,xmlXPathObjectPtr list)
1405 switch (list->type) {
1406 case XPATH_NODESET:{
1409 if (list->nodesetval) {
1410 for (indx = 0; indx < list->nodesetval->nodeNr;
1413 fprintf(stderr, " -------\n");
1414 xmlShellPrintNodeCtxt(ctxt,
1415 list->nodesetval->nodeTab[indx]);
1418 xmlGenericError(xmlGenericErrorContext,
1419 "Empty node set\n");
1424 xmlGenericError(xmlGenericErrorContext,
1425 "Is a Boolean:%s\n",
1426 xmlBoolToText(list->boolval));
1429 xmlGenericError(xmlGenericErrorContext,
1430 "Is a number:%0g\n", list->floatval);
1433 xmlGenericError(xmlGenericErrorContext,
1434 "Is a string:%s\n", list->stringval);
1438 xmlShellPrintXPathError(list->type, NULL);
1444 * xmlShellPrintXPathResult:
1445 * @list: a valid result generated by an xpath evaluation
1447 * Prints result to the output FILE
1450 xmlShellPrintXPathResult(xmlXPathObjectPtr list)
1452 xmlShellPrintXPathResultCtxt(NULL, list);
1457 * @ctxt: the shell context
1462 * Implements the XML shell function "ls"
1463 * Does an Unix like listing of the given node (like a directory)
1468 xmlShellList(xmlShellCtxtPtr ctxt,
1469 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1470 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1476 fprintf(ctxt->output, "NULL\n");
1479 if ((node->type == XML_DOCUMENT_NODE) ||
1480 (node->type == XML_HTML_DOCUMENT_NODE)) {
1481 cur = ((xmlDocPtr) node)->children;
1482 } else if (node->type == XML_NAMESPACE_DECL) {
1483 xmlLsOneNode(ctxt->output, node);
1485 } else if (node->children != NULL) {
1486 cur = node->children;
1488 xmlLsOneNode(ctxt->output, node);
1491 while (cur != NULL) {
1492 xmlLsOneNode(ctxt->output, cur);
1500 * @ctxt: the shell context
1505 * Implements the XML shell function "base"
1506 * dumps the current XML base of the node
1511 xmlShellBase(xmlShellCtxtPtr ctxt,
1512 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1513 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1519 fprintf(ctxt->output, "NULL\n");
1523 base = xmlNodeGetBase(node->doc, node);
1526 fprintf(ctxt->output, " No base found !!!\n");
1528 fprintf(ctxt->output, "%s\n", base);
1536 * @ctxt: the shell context
1537 * @arg: the new base
1541 * Implements the XML shell function "setbase"
1542 * change the current XML base of the node
1547 xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1548 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1549 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1551 xmlNodeSetBase(node, (xmlChar*) arg);
1557 * @ctxt: the shell context
1558 * @arg: the string or regular expression to find
1562 * Implements the XML shell function "grep"
1563 * dumps informations about the node (namespace, attributes, content).
1568 xmlShellGrep(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1569 char *arg, xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1577 #ifdef LIBXML_REGEXP_ENABLED
1578 if ((xmlStrchr((xmlChar *) arg, '?')) ||
1579 (xmlStrchr((xmlChar *) arg, '*')) ||
1580 (xmlStrchr((xmlChar *) arg, '.')) ||
1581 (xmlStrchr((xmlChar *) arg, '['))) {
1584 while (node != NULL) {
1585 if (node->type == XML_COMMENT_NODE) {
1586 if (xmlStrstr(node->content, (xmlChar *) arg)) {
1588 fprintf(ctxt->output, "%s : ", xmlGetNodePath(node));
1589 xmlShellList(ctxt, NULL, node, NULL);
1591 } else if (node->type == XML_TEXT_NODE) {
1592 if (xmlStrstr(node->content, (xmlChar *) arg)) {
1594 fprintf(ctxt->output, "%s : ", xmlGetNodePath(node->parent));
1595 xmlShellList(ctxt, NULL, node->parent, NULL);
1600 * Browse the full subtree, deep first
1603 if ((node->type == XML_DOCUMENT_NODE) ||
1604 (node->type == XML_HTML_DOCUMENT_NODE)) {
1605 node = ((xmlDocPtr) node)->children;
1606 } else if ((node->children != NULL)
1607 && (node->type != XML_ENTITY_REF_NODE)) {
1609 node = node->children;
1610 } else if (node->next != NULL) {
1614 /* go up to parents->next if needed */
1615 while (node != NULL) {
1616 if (node->parent != NULL) {
1617 node = node->parent;
1619 if (node->next != NULL) {
1623 if (node->parent == NULL) {
1635 * @ctxt: the shell context
1640 * Implements the XML shell function "dir"
1641 * dumps informations about the node (namespace, attributes, content).
1646 xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
1647 char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
1648 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1653 fprintf(ctxt->output, "NULL\n");
1656 if ((node->type == XML_DOCUMENT_NODE) ||
1657 (node->type == XML_HTML_DOCUMENT_NODE)) {
1658 xmlDebugDumpDocumentHead(ctxt->output, (xmlDocPtr) node);
1659 } else if (node->type == XML_ATTRIBUTE_NODE) {
1660 xmlDebugDumpAttr(ctxt->output, (xmlAttrPtr) node, 0);
1662 xmlDebugDumpOneNode(ctxt->output, node, 0);
1669 * @ctxt: the shell context
1674 * Implements the XML shell function "cat"
1675 * dumps the serialization node content (XML or HTML).
1680 xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
1681 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
1686 fprintf(ctxt->output, "NULL\n");
1689 if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
1690 #ifdef LIBXML_HTML_ENABLED
1691 if (node->type == XML_HTML_DOCUMENT_NODE)
1692 htmlDocDump(ctxt->output, (htmlDocPtr) node);
1694 htmlNodeDumpFile(ctxt->output, ctxt->doc, node);
1696 if (node->type == XML_DOCUMENT_NODE)
1697 xmlDocDump(ctxt->output, (xmlDocPtr) node);
1699 xmlElemDump(ctxt->output, ctxt->doc, node);
1700 #endif /* LIBXML_HTML_ENABLED */
1702 if (node->type == XML_DOCUMENT_NODE)
1703 xmlDocDump(ctxt->output, (xmlDocPtr) node);
1705 xmlElemDump(ctxt->output, ctxt->doc, node);
1707 fprintf(ctxt->output, "\n");
1713 * @ctxt: the shell context
1714 * @filename: the file name
1718 * Implements the XML shell function "load"
1719 * loads a new document specified by the filename
1721 * Returns 0 or -1 if loading failed
1724 xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename,
1725 xmlNodePtr node ATTRIBUTE_UNUSED,
1726 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1731 if (ctxt->doc != NULL)
1732 html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
1735 #ifdef LIBXML_HTML_ENABLED
1736 doc = htmlParseFile(filename, NULL);
1738 fprintf(ctxt->output, "HTML support not compiled in\n");
1740 #endif /* LIBXML_HTML_ENABLED */
1742 doc = xmlParseFile(filename);
1745 if (ctxt->loaded == 1) {
1746 xmlFreeDoc(ctxt->doc);
1749 #ifdef LIBXML_XPATH_ENABLED
1750 xmlXPathFreeContext(ctxt->pctxt);
1751 #endif /* LIBXML_XPATH_ENABLED */
1752 xmlFree(ctxt->filename);
1754 ctxt->node = (xmlNodePtr) doc;
1755 #ifdef LIBXML_XPATH_ENABLED
1756 ctxt->pctxt = xmlXPathNewContext(doc);
1757 #endif /* LIBXML_XPATH_ENABLED */
1758 ctxt->filename = (char *) xmlCanonicPath((xmlChar *) filename);
1766 * @ctxt: the shell context
1767 * @filename: the file name
1768 * @node: a node in the tree
1771 * Implements the XML shell function "write"
1772 * Write the current node to the filename, it saves the serialization
1773 * of the subtree under the @node specified
1775 * Returns 0 or -1 in case of error
1778 xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
1779 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1783 if ((filename == NULL) || (filename[0] == 0)) {
1784 xmlGenericError(xmlGenericErrorContext,
1785 "Write command requires a filename argument\n");
1789 if (access((char *) filename, W_OK)) {
1790 xmlGenericError(xmlGenericErrorContext,
1791 "Cannot write to %s\n", filename);
1795 switch (node->type) {
1796 case XML_DOCUMENT_NODE:
1797 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1798 xmlGenericError(xmlGenericErrorContext,
1799 "Failed to write to %s\n", filename);
1803 case XML_HTML_DOCUMENT_NODE:
1804 #ifdef LIBXML_HTML_ENABLED
1805 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1806 xmlGenericError(xmlGenericErrorContext,
1807 "Failed to write to %s\n", filename);
1811 if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
1812 xmlGenericError(xmlGenericErrorContext,
1813 "Failed to write to %s\n", filename);
1816 #endif /* LIBXML_HTML_ENABLED */
1821 f = fopen((char *) filename, "w");
1823 xmlGenericError(xmlGenericErrorContext,
1824 "Failed to write to %s\n", filename);
1827 xmlElemDump(f, ctxt->doc, node);
1836 * @ctxt: the shell context
1837 * @filename: the file name (optional)
1841 * Implements the XML shell function "save"
1842 * Write the current document to the filename, or it's original name
1844 * Returns 0 or -1 in case of error
1847 xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
1848 xmlNodePtr node ATTRIBUTE_UNUSED,
1849 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1851 if (ctxt->doc == NULL)
1853 if ((filename == NULL) || (filename[0] == 0))
1854 filename = ctxt->filename;
1856 if (access((char *) filename, W_OK)) {
1857 xmlGenericError(xmlGenericErrorContext,
1858 "Cannot save to %s\n", filename);
1862 switch (ctxt->doc->type) {
1863 case XML_DOCUMENT_NODE:
1864 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1865 xmlGenericError(xmlGenericErrorContext,
1866 "Failed to save to %s\n", filename);
1869 case XML_HTML_DOCUMENT_NODE:
1870 #ifdef LIBXML_HTML_ENABLED
1871 if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
1872 xmlGenericError(xmlGenericErrorContext,
1873 "Failed to save to %s\n", filename);
1876 if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
1877 xmlGenericError(xmlGenericErrorContext,
1878 "Failed to save to %s\n", filename);
1880 #endif /* LIBXML_HTML_ENABLED */
1883 xmlGenericError(xmlGenericErrorContext,
1884 "To save to subparts of a document use the 'write' command\n");
1893 * @ctxt: the shell context
1894 * @dtd: the DTD URI (optional)
1898 * Implements the XML shell function "validate"
1899 * Validate the document, if a DTD path is provided, then the validation
1900 * is done against the given DTD.
1902 * Returns 0 or -1 in case of error
1905 xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd,
1906 xmlNodePtr node ATTRIBUTE_UNUSED,
1907 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1912 vctxt.userData = stderr;
1913 vctxt.error = (xmlValidityErrorFunc) fprintf;
1914 vctxt.warning = (xmlValidityWarningFunc) fprintf;
1916 if ((dtd == NULL) || (dtd[0] == 0)) {
1917 res = xmlValidateDocument(&vctxt, ctxt->doc);
1921 subset = xmlParseDTD(NULL, (xmlChar *) dtd);
1922 if (subset != NULL) {
1923 res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
1933 * @ctxt: the shell context
1935 * @tree: a node defining a subtree
1938 * Implements the XML shell function "du"
1939 * show the structure of the subtree under node @tree
1940 * If @tree is null, the command works on the current node.
1942 * Returns 0 or -1 in case of error
1945 xmlShellDu(xmlShellCtxtPtr ctxt,
1946 char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree,
1947 xmlNodePtr node2 ATTRIBUTE_UNUSED)
1958 while (node != NULL) {
1959 if ((node->type == XML_DOCUMENT_NODE) ||
1960 (node->type == XML_HTML_DOCUMENT_NODE)) {
1961 fprintf(ctxt->output, "/\n");
1962 } else if (node->type == XML_ELEMENT_NODE) {
1963 for (i = 0; i < indent; i++)
1964 fprintf(ctxt->output, " ");
1965 fprintf(ctxt->output, "%s\n", node->name);
1970 * Browse the full subtree, deep first
1973 if ((node->type == XML_DOCUMENT_NODE) ||
1974 (node->type == XML_HTML_DOCUMENT_NODE)) {
1975 node = ((xmlDocPtr) node)->children;
1976 } else if ((node->children != NULL)
1977 && (node->type != XML_ENTITY_REF_NODE)) {
1979 node = node->children;
1981 } else if ((node != tree) && (node->next != NULL)) {
1984 } else if (node != tree) {
1985 /* go up to parents->next if needed */
1986 while (node != tree) {
1987 if (node->parent != NULL) {
1988 node = node->parent;
1991 if ((node != tree) && (node->next != NULL)) {
1995 if (node->parent == NULL) {
2004 /* exit condition */
2015 * @ctxt: the shell context
2016 * @buffer: the output buffer
2020 * Implements the XML shell function "pwd"
2021 * Show the full path from the root to the node, if needed building
2022 * thumblers when similar elements exists at a given ancestor level.
2023 * The output is compatible with XPath commands.
2025 * Returns 0 or -1 in case of error
2028 xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
2029 xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
2036 path = xmlGetNodePath(node);
2041 * This test prevents buffer overflow, because this routine
2042 * is only called by xmlShell, in which the second argument is
2044 * It is a dirty hack before a cleaner solution is found.
2045 * Documentation should mention that the second argument must
2046 * be at least 500 chars long, and could be stripped if too long.
2048 snprintf(buffer, 499, "%s", path);
2057 * @doc: the initial document
2058 * @filename: the output buffer
2059 * @input: the line reading function
2060 * @output: the output FILE*, defaults to stdout if NULL
2062 * Implements the XML shell
2063 * This allow to load, validate, view, modify and save a document
2064 * using a environment similar to a UNIX commandline.
2067 xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
2070 char prompt[500] = "/ > ";
2071 char *cmdline = NULL, *cur;
2076 xmlShellCtxtPtr ctxt;
2077 xmlXPathObjectPtr list;
2081 if (filename == NULL)
2087 ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
2092 ctxt->input = input;
2093 ctxt->output = output;
2094 ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
2095 ctxt->node = (xmlNodePtr) ctxt->doc;
2097 #ifdef LIBXML_XPATH_ENABLED
2098 ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
2099 if (ctxt->pctxt == NULL) {
2103 #endif /* LIBXML_XPATH_ENABLED */
2105 if (ctxt->node == (xmlNodePtr) ctxt->doc)
2106 snprintf(prompt, sizeof(prompt), "%s > ", "/");
2107 else if ((ctxt->node != NULL) && (ctxt->node->name))
2108 snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
2110 snprintf(prompt, sizeof(prompt), "? > ");
2111 prompt[sizeof(prompt) - 1] = 0;
2114 * Get a new command line
2116 cmdline = ctxt->input(prompt);
2117 if (cmdline == NULL)
2121 * Parse the command itself
2125 while ((*cur == ' ') || (*cur == '\t'))
2128 while ((*cur != ' ') && (*cur != '\t') &&
2129 (*cur != '\n') && (*cur != '\r')) {
2132 command[i++] = *cur++;
2140 * Parse the argument
2142 while ((*cur == ' ') || (*cur == '\t'))
2145 while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
2155 * start interpreting the command
2157 if (!strcmp(command, "exit"))
2159 if (!strcmp(command, "quit"))
2161 if (!strcmp(command, "bye"))
2163 if (!strcmp(command, "help")) {
2164 fprintf(ctxt->output, "\tbase display XML base of the node\n");
2165 fprintf(ctxt->output, "\tsetbase URI change the XML base of the node\n");
2166 fprintf(ctxt->output, "\tbye leave shell\n");
2167 fprintf(ctxt->output, "\tcat [node] display node or current node\n");
2168 fprintf(ctxt->output, "\tcd [path] change directory to path or to root\n");
2169 fprintf(ctxt->output, "\tdir [path] dumps informations about the node (namespace, attributes, content)\n");
2170 fprintf(ctxt->output, "\tdu [path] show the structure of the subtree under path or the current node\n");
2171 fprintf(ctxt->output, "\texit leave shell\n");
2172 fprintf(ctxt->output, "\thelp display this help\n");
2173 fprintf(ctxt->output, "\tfree display memory usage\n");
2174 fprintf(ctxt->output, "\tload [name] load a new document with name\n");
2175 fprintf(ctxt->output, "\tls [path] list contents of path or the current directory\n");
2176 #ifdef LIBXML_XPATH_ENABLED
2177 fprintf(ctxt->output, "\txpath expr evaluate the XPath expression in that context and print the result\n");
2178 #endif /* LIBXML_XPATH_ENABLED */
2179 fprintf(ctxt->output, "\tpwd display current working directory\n");
2180 fprintf(ctxt->output, "\tquit leave shell\n");
2181 fprintf(ctxt->output, "\tsave [name] save this document to name or the original name\n");
2182 fprintf(ctxt->output, "\tvalidate check the document for errors\n");
2183 fprintf(ctxt->output, "\twrite [name] write the current node to the filename\n");
2184 fprintf(ctxt->output, "\tgrep string search for a string in the subtree\n");
2185 } else if (!strcmp(command, "validate")) {
2186 xmlShellValidate(ctxt, arg, NULL, NULL);
2187 } else if (!strcmp(command, "load")) {
2188 xmlShellLoad(ctxt, arg, NULL, NULL);
2189 } else if (!strcmp(command, "save")) {
2190 xmlShellSave(ctxt, arg, NULL, NULL);
2191 } else if (!strcmp(command, "write")) {
2192 xmlShellWrite(ctxt, arg, NULL, NULL);
2193 } else if (!strcmp(command, "grep")) {
2194 xmlShellGrep(ctxt, arg, ctxt->node, NULL);
2195 } else if (!strcmp(command, "free")) {
2197 xmlMemShow(ctxt->output, 0);
2201 sscanf(arg, "%d", &len);
2202 xmlMemShow(ctxt->output, len);
2204 } else if (!strcmp(command, "pwd")) {
2207 if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
2208 fprintf(ctxt->output, "%s\n", dir);
2209 } else if (!strcmp(command, "du")) {
2210 xmlShellDu(ctxt, NULL, ctxt->node, NULL);
2211 } else if (!strcmp(command, "base")) {
2212 xmlShellBase(ctxt, NULL, ctxt->node, NULL);
2213 #ifdef LIBXML_XPATH_ENABLED
2214 } else if (!strcmp(command, "xpath")) {
2216 xmlGenericError(xmlGenericErrorContext,
2217 "xpath: expression required\n");
2219 ctxt->pctxt->node = ctxt->node;
2220 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2221 xmlXPathDebugDumpObject(ctxt->output, list, 0);
2222 xmlXPathFreeObject(list);
2224 #endif /* LIBXML_XPATH_ENABLED */
2225 } else if (!strcmp(command, "setbase")) {
2226 xmlShellSetBase(ctxt, arg, ctxt->node, NULL);
2227 } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) {
2228 int dir = (!strcmp(command, "dir"));
2232 xmlShellDir(ctxt, NULL, ctxt->node, NULL);
2234 xmlShellList(ctxt, NULL, ctxt->node, NULL);
2236 ctxt->pctxt->node = ctxt->node;
2237 #ifdef LIBXML_XPATH_ENABLED
2238 ctxt->pctxt->node = ctxt->node;
2239 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2242 #endif /* LIBXML_XPATH_ENABLED */
2244 switch (list->type) {
2245 case XPATH_UNDEFINED:
2246 xmlGenericError(xmlGenericErrorContext,
2247 "%s: no such node\n", arg);
2249 case XPATH_NODESET:{
2252 if (list->nodesetval == NULL)
2256 indx < list->nodesetval->nodeNr;
2259 xmlShellDir(ctxt, NULL,
2261 nodeTab[indx], NULL);
2263 xmlShellList(ctxt, NULL,
2265 nodeTab[indx], NULL);
2270 xmlGenericError(xmlGenericErrorContext,
2271 "%s is a Boolean\n", arg);
2274 xmlGenericError(xmlGenericErrorContext,
2275 "%s is a number\n", arg);
2278 xmlGenericError(xmlGenericErrorContext,
2279 "%s is a string\n", arg);
2282 xmlGenericError(xmlGenericErrorContext,
2283 "%s is a point\n", arg);
2286 xmlGenericError(xmlGenericErrorContext,
2287 "%s is a range\n", arg);
2289 case XPATH_LOCATIONSET:
2290 xmlGenericError(xmlGenericErrorContext,
2291 "%s is a range\n", arg);
2294 xmlGenericError(xmlGenericErrorContext,
2295 "%s is user-defined\n", arg);
2297 case XPATH_XSLT_TREE:
2298 xmlGenericError(xmlGenericErrorContext,
2299 "%s is an XSLT value tree\n",
2303 #ifdef LIBXML_XPATH_ENABLED
2304 xmlXPathFreeObject(list);
2307 xmlGenericError(xmlGenericErrorContext,
2308 "%s: no such node\n", arg);
2310 ctxt->pctxt->node = NULL;
2312 } else if (!strcmp(command, "cd")) {
2314 ctxt->node = (xmlNodePtr) ctxt->doc;
2316 #ifdef LIBXML_XPATH_ENABLED
2317 ctxt->pctxt->node = ctxt->node;
2318 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2321 #endif /* LIBXML_XPATH_ENABLED */
2323 switch (list->type) {
2324 case XPATH_UNDEFINED:
2325 xmlGenericError(xmlGenericErrorContext,
2326 "%s: no such node\n", arg);
2329 if (list->nodesetval != NULL) {
2330 if (list->nodesetval->nodeNr == 1) {
2331 ctxt->node = list->nodesetval->nodeTab[0];
2332 if ((ctxt->node != NULL) &&
2333 (ctxt->node->type ==
2334 XML_NAMESPACE_DECL)) {
2335 xmlGenericError(xmlGenericErrorContext,
2336 "cannot cd to namespace\n");
2340 xmlGenericError(xmlGenericErrorContext,
2341 "%s is a %d Node Set\n",
2343 list->nodesetval->nodeNr);
2345 xmlGenericError(xmlGenericErrorContext,
2346 "%s is an empty Node Set\n",
2350 xmlGenericError(xmlGenericErrorContext,
2351 "%s is a Boolean\n", arg);
2354 xmlGenericError(xmlGenericErrorContext,
2355 "%s is a number\n", arg);
2358 xmlGenericError(xmlGenericErrorContext,
2359 "%s is a string\n", arg);
2362 xmlGenericError(xmlGenericErrorContext,
2363 "%s is a point\n", arg);
2366 xmlGenericError(xmlGenericErrorContext,
2367 "%s is a range\n", arg);
2369 case XPATH_LOCATIONSET:
2370 xmlGenericError(xmlGenericErrorContext,
2371 "%s is a range\n", arg);
2374 xmlGenericError(xmlGenericErrorContext,
2375 "%s is user-defined\n", arg);
2377 case XPATH_XSLT_TREE:
2378 xmlGenericError(xmlGenericErrorContext,
2379 "%s is an XSLT value tree\n",
2383 #ifdef LIBXML_XPATH_ENABLED
2384 xmlXPathFreeObject(list);
2387 xmlGenericError(xmlGenericErrorContext,
2388 "%s: no such node\n", arg);
2390 ctxt->pctxt->node = NULL;
2392 } else if (!strcmp(command, "cat")) {
2394 xmlShellCat(ctxt, NULL, ctxt->node, NULL);
2396 ctxt->pctxt->node = ctxt->node;
2397 #ifdef LIBXML_XPATH_ENABLED
2398 ctxt->pctxt->node = ctxt->node;
2399 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
2402 #endif /* LIBXML_XPATH_ENABLED */
2404 switch (list->type) {
2405 case XPATH_UNDEFINED:
2406 xmlGenericError(xmlGenericErrorContext,
2407 "%s: no such node\n", arg);
2409 case XPATH_NODESET:{
2412 if (list->nodesetval == NULL)
2416 indx < list->nodesetval->nodeNr;
2419 fprintf(ctxt->output, " -------\n");
2420 xmlShellCat(ctxt, NULL,
2422 nodeTab[indx], NULL);
2427 xmlGenericError(xmlGenericErrorContext,
2428 "%s is a Boolean\n", arg);
2431 xmlGenericError(xmlGenericErrorContext,
2432 "%s is a number\n", arg);
2435 xmlGenericError(xmlGenericErrorContext,
2436 "%s is a string\n", arg);
2439 xmlGenericError(xmlGenericErrorContext,
2440 "%s is a point\n", arg);
2443 xmlGenericError(xmlGenericErrorContext,
2444 "%s is a range\n", arg);
2446 case XPATH_LOCATIONSET:
2447 xmlGenericError(xmlGenericErrorContext,
2448 "%s is a range\n", arg);
2451 xmlGenericError(xmlGenericErrorContext,
2452 "%s is user-defined\n", arg);
2454 case XPATH_XSLT_TREE:
2455 xmlGenericError(xmlGenericErrorContext,
2456 "%s is an XSLT value tree\n",
2460 #ifdef LIBXML_XPATH_ENABLED
2461 xmlXPathFreeObject(list);
2464 xmlGenericError(xmlGenericErrorContext,
2465 "%s: no such node\n", arg);
2467 ctxt->pctxt->node = NULL;
2470 xmlGenericError(xmlGenericErrorContext,
2471 "Unknown command %s\n", command);
2473 free(cmdline); /* not xmlFree here ! */
2475 #ifdef LIBXML_XPATH_ENABLED
2476 xmlXPathFreeContext(ctxt->pctxt);
2477 #endif /* LIBXML_XPATH_ENABLED */
2479 xmlFreeDoc(ctxt->doc);
2481 if (ctxt->filename != NULL)
2482 xmlFree(ctxt->filename);
2484 if (cmdline != NULL)
2485 free(cmdline); /* not xmlFree here ! */
2488 #endif /* LIBXML_DEBUG_ENABLED */