debugXML.c
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:45k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

C/C++

  1. /*
  2.  * debugXML.c : This is a set of routines used for debugging the tree
  3.  *              produced by the XML parser.
  4.  *
  5.  * See Copyright for the status of this software.
  6.  *
  7.  * Daniel Veillard <Daniel.Veillard@w3.org>
  8.  */
  9. #ifdef WIN32
  10. #include "win32config.h"
  11. #else
  12. #include "config.h"
  13. #endif
  14. #include "xmlversion.h"
  15. #ifdef LIBXML_DEBUG_ENABLED
  16. #include <stdio.h>
  17. #ifdef HAVE_STDLIB_H
  18. #include <stdlib.h>
  19. #endif
  20. #ifdef HAVE_STRING_H
  21. #include <string.h>
  22. #endif
  23. #include <libxml/xmlmemory.h>
  24. #include <libxml/tree.h>
  25. #include <libxml/parser.h>
  26. #include <libxml/valid.h>
  27. #include <libxml/debugXML.h>
  28. #include <libxml/HTMLtree.h>
  29. #include <libxml/HTMLparser.h>
  30. #define IS_BLANK(c)
  31.   (((c) == 'n') || ((c) == 'r') || ((c) == 't') || ((c) == ' '))
  32. void xmlDebugDumpString(FILE *output, const xmlChar *str) {
  33.     int i;
  34.     for (i = 0;i < 40;i++)
  35.         if (str[i] == 0) return;
  36. else if (IS_BLANK(str[i])) fputc(' ', output);
  37. else fputc(str[i], output);
  38.     fprintf(output, "...");
  39. }
  40. void xmlDebugDumpDtd(FILE *output, xmlDtdPtr dtd, int depth) {
  41.     int i;
  42.     char shift[100];
  43.     for (i = 0;((i < depth) && (i < 25));i++)
  44.         shift[2 * i] = shift[2 * i + 1] = ' ';
  45.     shift[2 * i] = shift[2 * i + 1] = 0;
  46.     fprintf(output, shift);
  47.     if (dtd->type != XML_DTD_NODE) {
  48. fprintf(output, "PBM: not a DTDn");
  49. return;
  50.     }
  51.     if (dtd->name != NULL)
  52. fprintf(output, "DTD(%s)", dtd->name);
  53.     else
  54. fprintf(output, "DTD");
  55.     if (dtd->ExternalID != NULL)
  56. fprintf(output, ", PUBLIC %s", dtd->ExternalID);
  57.     if (dtd->SystemID != NULL)
  58. fprintf(output, ", SYSTEM %s", dtd->SystemID);
  59.     fprintf(output, "n");
  60.     /*
  61.      * Do a bit of checking
  62.      */
  63.     if (dtd->parent == NULL)
  64. fprintf(output, "PBM: Dtd has no parentn");
  65.     if (dtd->doc == NULL)
  66. fprintf(output, "PBM: Dtd has no docn");
  67.     if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
  68. fprintf(output, "PBM: Dtd doc differs from parent's onen");
  69.     if (dtd->prev == NULL) {
  70. if ((dtd->parent != NULL) && (dtd->parent->children != (xmlNodePtr)dtd))
  71.     fprintf(output, "PBM: Dtd has no prev and not first of listn");
  72.     } else {
  73. if (dtd->prev->next != (xmlNodePtr) dtd)
  74.     fprintf(output, "PBM: Dtd prev->next : back link wrongn");
  75.     }
  76.     if (dtd->next == NULL) {
  77. if ((dtd->parent != NULL) && (dtd->parent->last != (xmlNodePtr) dtd))
  78.     fprintf(output, "PBM: Dtd has no next and not last of listn");
  79.     } else {
  80. if (dtd->next->prev != (xmlNodePtr) dtd)
  81.     fprintf(output, "PBM: Dtd next->prev : forward link wrongn");
  82.     }
  83. }
  84. void xmlDebugDumpAttrDecl(FILE *output, xmlAttributePtr attr, int depth) {
  85.     int i;
  86.     char shift[100];
  87.     for (i = 0;((i < depth) && (i < 25));i++)
  88.         shift[2 * i] = shift[2 * i + 1] = ' ';
  89.     shift[2 * i] = shift[2 * i + 1] = 0;
  90.     fprintf(output, shift);
  91.     if (attr->type != XML_ATTRIBUTE_DECL) {
  92. fprintf(output, "PBM: not a Attrn");
  93. return;
  94.     }
  95.     if (attr->name != NULL)
  96. fprintf(output, "ATTRDECL(%s)", attr->name);
  97.     else
  98. fprintf(output, "PBM ATTRDECL noname!!!");
  99.     if (attr->elem != NULL)
  100. fprintf(output, " for %s", attr->elem);
  101.     else
  102. fprintf(output, " PBM noelem!!!");
  103.     switch (attr->atype) {
  104.         case XML_ATTRIBUTE_CDATA:
  105.     fprintf(output, " CDATA");
  106.     break;
  107.         case XML_ATTRIBUTE_ID:
  108.     fprintf(output, " ID");
  109.     break;
  110.         case XML_ATTRIBUTE_IDREF:
  111.     fprintf(output, " IDREF");
  112.     break;
  113.         case XML_ATTRIBUTE_IDREFS:
  114.     fprintf(output, " IDREFS");
  115.     break;
  116.         case XML_ATTRIBUTE_ENTITY:
  117.     fprintf(output, " ENTITY");
  118.     break;
  119.         case XML_ATTRIBUTE_ENTITIES:
  120.     fprintf(output, " ENTITIES");
  121.     break;
  122.         case XML_ATTRIBUTE_NMTOKEN:
  123.     fprintf(output, " NMTOKEN");
  124.     break;
  125.         case XML_ATTRIBUTE_NMTOKENS:
  126.     fprintf(output, " NMTOKENS");
  127.     break;
  128.         case XML_ATTRIBUTE_ENUMERATION:
  129.     fprintf(output, " ENUMERATION");
  130.     break;
  131.         case XML_ATTRIBUTE_NOTATION:
  132.     fprintf(output, " NOTATION ");
  133.     break;
  134.     }
  135.     if (attr->tree != NULL) {
  136. int i;
  137. xmlEnumerationPtr cur = attr->tree;
  138. for (i = 0;i < 5; i++) {
  139.     if (i != 0)
  140. fprintf(output, "|%s", cur->name);
  141.     else
  142. fprintf(output, " (%s", cur->name);
  143.     cur = cur->next;
  144.     if (cur == NULL) break;
  145. }
  146. if (cur == NULL)
  147.     fprintf(output, ")");
  148. else
  149.     fprintf(output, "...)");
  150.     }
  151.     switch (attr->def) {
  152.         case XML_ATTRIBUTE_NONE:
  153.     break;
  154.         case XML_ATTRIBUTE_REQUIRED:
  155.     fprintf(output, " REQUIRED");
  156.     break;
  157.         case XML_ATTRIBUTE_IMPLIED:
  158.     fprintf(output, " IMPLIED");
  159.     break;
  160.         case XML_ATTRIBUTE_FIXED:
  161.     fprintf(output, " FIXED");
  162.     break;
  163.     }
  164.     if (attr->defaultValue != NULL) {
  165. fprintf(output, """);
  166. xmlDebugDumpString(output, attr->defaultValue);
  167. fprintf(output, """);
  168.     }
  169.     printf("n");
  170.     /*
  171.      * Do a bit of checking
  172.      */
  173.     if (attr->parent == NULL)
  174. fprintf(output, "PBM: Attr has no parentn");
  175.     if (attr->doc == NULL)
  176. fprintf(output, "PBM: Attr has no docn");
  177.     if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
  178. fprintf(output, "PBM: Attr doc differs from parent's onen");
  179.     if (attr->prev == NULL) {
  180. if ((attr->parent != NULL) && (attr->parent->children != (xmlNodePtr)attr))
  181.     fprintf(output, "PBM: Attr has no prev and not first of listn");
  182.     } else {
  183. if (attr->prev->next != (xmlNodePtr) attr)
  184.     fprintf(output, "PBM: Attr prev->next : back link wrongn");
  185.     }
  186.     if (attr->next == NULL) {
  187. if ((attr->parent != NULL) && (attr->parent->last != (xmlNodePtr) attr))
  188.     fprintf(output, "PBM: Attr has no next and not last of listn");
  189.     } else {
  190. if (attr->next->prev != (xmlNodePtr) attr)
  191.     fprintf(output, "PBM: Attr next->prev : forward link wrongn");
  192.     }
  193. }
  194. void xmlDebugDumpElemDecl(FILE *output, xmlElementPtr elem, int depth) {
  195.     int i;
  196.     char shift[100];
  197.     for (i = 0;((i < depth) && (i < 25));i++)
  198.         shift[2 * i] = shift[2 * i + 1] = ' ';
  199.     shift[2 * i] = shift[2 * i + 1] = 0;
  200.     fprintf(output, shift);
  201.     if (elem->type != XML_ELEMENT_DECL) {
  202. fprintf(output, "PBM: not a Elemn");
  203. return;
  204.     }
  205.     if (elem->name != NULL)
  206. fprintf(output, "ELEMDECL(%s)", elem->name);
  207.     else
  208. fprintf(output, "PBM ELEMDECL noname!!!");
  209.     switch (elem->etype) {
  210. case XML_ELEMENT_TYPE_EMPTY: 
  211.     fprintf(output, ", EMPTY");
  212.     break;
  213. case XML_ELEMENT_TYPE_ANY: 
  214.     fprintf(output, ", ANY");
  215.     break;
  216. case XML_ELEMENT_TYPE_MIXED: 
  217.     fprintf(output, ", MIXED ");
  218.     break;
  219. case XML_ELEMENT_TYPE_ELEMENT: 
  220.     fprintf(output, ", MIXED ");
  221.     break;
  222.     }
  223.     if (elem->content != NULL) {
  224. char buf[1001];
  225. buf[0] = 0;
  226. xmlSprintfElementContent(buf, elem->content, 1);
  227. buf[1000] = 0;
  228. fprintf(output, "%s", buf);
  229.     }
  230.     printf("n");
  231.     /*
  232.      * Do a bit of checking
  233.      */
  234.     if (elem->parent == NULL)
  235. fprintf(output, "PBM: Elem has no parentn");
  236.     if (elem->doc == NULL)
  237. fprintf(output, "PBM: Elem has no docn");
  238.     if ((elem->parent != NULL) && (elem->doc != elem->parent->doc))
  239. fprintf(output, "PBM: Elem doc differs from parent's onen");
  240.     if (elem->prev == NULL) {
  241. if ((elem->parent != NULL) && (elem->parent->children != (xmlNodePtr)elem))
  242.     fprintf(output, "PBM: Elem has no prev and not first of listn");
  243.     } else {
  244. if (elem->prev->next != (xmlNodePtr) elem)
  245.     fprintf(output, "PBM: Elem prev->next : back link wrongn");
  246.     }
  247.     if (elem->next == NULL) {
  248. if ((elem->parent != NULL) && (elem->parent->last != (xmlNodePtr) elem))
  249.     fprintf(output, "PBM: Elem has no next and not last of listn");
  250.     } else {
  251. if (elem->next->prev != (xmlNodePtr) elem)
  252.     fprintf(output, "PBM: Elem next->prev : forward link wrongn");
  253.     }
  254. }
  255. void xmlDebugDumpEntityDecl(FILE *output, xmlEntityPtr ent, int depth) {
  256.     int i;
  257.     char shift[100];
  258.     for (i = 0;((i < depth) && (i < 25));i++)
  259.         shift[2 * i] = shift[2 * i + 1] = ' ';
  260.     shift[2 * i] = shift[2 * i + 1] = 0;
  261.     fprintf(output, shift);
  262.     if (ent->type != XML_ENTITY_DECL) {
  263. fprintf(output, "PBM: not a Entity decln");
  264. return;
  265.     }
  266.     if (ent->name != NULL)
  267. fprintf(output, "ENTITYDECL(%s)", ent->name);
  268.     else
  269. fprintf(output, "PBM ENTITYDECL noname!!!");
  270.     switch (ent->etype) {
  271. case XML_INTERNAL_GENERAL_ENTITY: 
  272.     fprintf(output, ", internaln");
  273.     break;
  274. case XML_EXTERNAL_GENERAL_PARSED_ENTITY: 
  275.     fprintf(output, ", external parsedn");
  276.     break;
  277. case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: 
  278.     fprintf(output, ", unparsedn");
  279.     break;
  280. case XML_INTERNAL_PARAMETER_ENTITY: 
  281.     fprintf(output, ", parametern");
  282.     break;
  283. case XML_EXTERNAL_PARAMETER_ENTITY: 
  284.     fprintf(output, ", external parametern");
  285.     break;
  286. case XML_INTERNAL_PREDEFINED_ENTITY: 
  287.     fprintf(output, ", predefinedn");
  288.     break;
  289.     }
  290.     if (ent->ExternalID) {
  291.         fprintf(output, shift);
  292.         fprintf(output, "ExternalID=%sn", ent->ExternalID);
  293.     }
  294.     if (ent->SystemID) {
  295.         fprintf(output, shift);
  296.         fprintf(output, "SystemID=%sn", ent->SystemID);
  297.     }
  298.     if (ent->content) {
  299.         fprintf(output, shift);
  300. fprintf(output, "content=");
  301. xmlDebugDumpString(output, ent->content);
  302. fprintf(output, "n");
  303.     }
  304.     /*
  305.      * Do a bit of checking
  306.      */
  307.     if (ent->parent == NULL)
  308. fprintf(output, "PBM: Ent has no parentn");
  309.     if (ent->doc == NULL)
  310. fprintf(output, "PBM: Ent has no docn");
  311.     if ((ent->parent != NULL) && (ent->doc != ent->parent->doc))
  312. fprintf(output, "PBM: Ent doc differs from parent's onen");
  313.     if (ent->prev == NULL) {
  314. if ((ent->parent != NULL) && (ent->parent->children != (xmlNodePtr)ent))
  315.     fprintf(output, "PBM: Ent has no prev and not first of listn");
  316.     } else {
  317. if (ent->prev->next != (xmlNodePtr) ent)
  318.     fprintf(output, "PBM: Ent prev->next : back link wrongn");
  319.     }
  320.     if (ent->next == NULL) {
  321. if ((ent->parent != NULL) && (ent->parent->last != (xmlNodePtr) ent))
  322.     fprintf(output, "PBM: Ent has no next and not last of listn");
  323.     } else {
  324. if (ent->next->prev != (xmlNodePtr) ent)
  325.     fprintf(output, "PBM: Ent next->prev : forward link wrongn");
  326.     }
  327. }
  328. void xmlDebugDumpNamespace(FILE *output, xmlNsPtr ns, int depth) {
  329.     int i;
  330.     char shift[100];
  331.     for (i = 0;((i < depth) && (i < 25));i++)
  332.         shift[2 * i] = shift[2 * i + 1] = ' ';
  333.     shift[2 * i] = shift[2 * i + 1] = 0;
  334.     fprintf(output, shift);
  335.     if (ns->type == XML_GLOBAL_NAMESPACE)
  336.         fprintf(output, "old ");
  337.     if (ns->prefix != NULL)
  338. fprintf(output, "namespace %s href=", ns->prefix);
  339.     else
  340. fprintf(output, "default namespace href=");
  341.     xmlDebugDumpString(output, ns->href);
  342.     fprintf(output, "n");
  343. }
  344. void xmlDebugDumpNamespaceList(FILE *output, xmlNsPtr ns, int depth) {
  345.     while (ns != NULL) {
  346.         xmlDebugDumpNamespace(output, ns, depth);
  347. ns = ns->next;
  348.     }
  349. }
  350. void xmlDebugDumpEntity(FILE *output, xmlEntityPtr ent, int depth) {
  351.     int i;
  352.     char shift[100];
  353.     for (i = 0;((i < depth) && (i < 25));i++)
  354.         shift[2 * i] = shift[2 * i + 1] = ' ';
  355.     shift[2 * i] = shift[2 * i + 1] = 0;
  356.     fprintf(output, shift);
  357.     switch (ent->etype) {
  358.         case XML_INTERNAL_GENERAL_ENTITY:
  359.     fprintf(output, "INTERNAL_GENERAL_ENTITY ");
  360.     break;
  361.         case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
  362.     fprintf(output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
  363.     break;
  364.         case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
  365.     fprintf(output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
  366.     break;
  367.         case XML_INTERNAL_PARAMETER_ENTITY:
  368.     fprintf(output, "INTERNAL_PARAMETER_ENTITY ");
  369.     break;
  370.         case XML_EXTERNAL_PARAMETER_ENTITY:
  371.     fprintf(output, "EXTERNAL_PARAMETER_ENTITY ");
  372.     break;
  373. default:
  374.     fprintf(output, "ENTITY_%d ! ", ent->etype);
  375.     }
  376.     fprintf(output, "%sn", ent->name);
  377.     if (ent->ExternalID) {
  378.         fprintf(output, shift);
  379.         fprintf(output, "ExternalID=%sn", ent->ExternalID);
  380.     }
  381.     if (ent->SystemID) {
  382.         fprintf(output, shift);
  383.         fprintf(output, "SystemID=%sn", ent->SystemID);
  384.     }
  385.     if (ent->content) {
  386.         fprintf(output, shift);
  387. fprintf(output, "content=");
  388. xmlDebugDumpString(output, ent->content);
  389. fprintf(output, "n");
  390.     }
  391. }
  392. void xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
  393.     int i;
  394.     char shift[100];
  395.     for (i = 0;((i < depth) && (i < 25));i++)
  396.         shift[2 * i] = shift[2 * i + 1] = ' ';
  397.     shift[2 * i] = shift[2 * i + 1] = 0;
  398.     fprintf(output, shift);
  399.     fprintf(output, "ATTRIBUTE %sn", attr->name);
  400.     if (attr->children != NULL) 
  401.         xmlDebugDumpNodeList(output, attr->children, depth + 1);
  402.     /*
  403.      * Do a bit of checking
  404.      */
  405.     if (attr->parent == NULL)
  406. fprintf(output, "PBM: Attr has no parentn");
  407.     if (attr->doc == NULL)
  408. fprintf(output, "PBM: Attr has no docn");
  409.     if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
  410. fprintf(output, "PBM: Attr doc differs from parent's onen");
  411.     if (attr->prev == NULL) {
  412. if ((attr->parent != NULL) && (attr->parent->properties != attr))
  413.     fprintf(output, "PBM: Attr has no prev and not first of listn");
  414.     } else {
  415. if (attr->prev->next != attr)
  416.     fprintf(output, "PBM: Attr prev->next : back link wrongn");
  417.     }
  418.     if (attr->next != NULL) {
  419. if (attr->next->prev != attr)
  420.     fprintf(output, "PBM: Attr next->prev : forward link wrongn");
  421.     }
  422. }
  423. void xmlDebugDumpAttrList(FILE *output, xmlAttrPtr attr, int depth) {
  424.     while (attr != NULL) {
  425.         xmlDebugDumpAttr(output, attr, depth);
  426. attr = attr->next;
  427.     }
  428. }
  429. void xmlDebugDumpOneNode(FILE *output, xmlNodePtr node, int depth) {
  430.     int i;
  431.     char shift[100];
  432.     for (i = 0;((i < depth) && (i < 25));i++)
  433.         shift[2 * i] = shift[2 * i + 1] = ' ';
  434.     shift[2 * i] = shift[2 * i + 1] = 0;
  435.     switch (node->type) {
  436. case XML_ELEMENT_NODE:
  437.     fprintf(output, shift);
  438.     fprintf(output, "ELEMENT ");
  439.     if (node->ns != NULL)
  440.         fprintf(output, "%s:%sn", node->ns->prefix, node->name);
  441.     else
  442.         fprintf(output, "%sn", node->name);
  443.     break;
  444. case XML_ATTRIBUTE_NODE:
  445.     fprintf(output, shift);
  446.     fprintf(output, "Error, ATTRIBUTE found heren");
  447.     break;
  448. case XML_TEXT_NODE:
  449.     fprintf(output, shift);
  450.     fprintf(output, "TEXTn");
  451.     break;
  452. case XML_CDATA_SECTION_NODE:
  453.     fprintf(output, shift);
  454.     fprintf(output, "CDATA_SECTIONn");
  455.     break;
  456. case XML_ENTITY_REF_NODE:
  457.     fprintf(output, shift);
  458.     fprintf(output, "ENTITY_REF(%s)n", node->name);
  459.     break;
  460. case XML_ENTITY_NODE:
  461.     fprintf(output, shift);
  462.     fprintf(output, "ENTITYn");
  463.     break;
  464. case XML_PI_NODE:
  465.     fprintf(output, shift);
  466.     fprintf(output, "PI %sn", node->name);
  467.     break;
  468. case XML_COMMENT_NODE:
  469.     fprintf(output, shift);
  470.     fprintf(output, "COMMENTn");
  471.     break;
  472. case XML_DOCUMENT_NODE:
  473. case XML_HTML_DOCUMENT_NODE:
  474.     fprintf(output, shift);
  475.     fprintf(output, "Error, DOCUMENT found heren");
  476.     break;
  477. case XML_DOCUMENT_TYPE_NODE:
  478.     fprintf(output, shift);
  479.     fprintf(output, "DOCUMENT_TYPEn");
  480.     break;
  481. case XML_DOCUMENT_FRAG_NODE:
  482.     fprintf(output, shift);
  483.     fprintf(output, "DOCUMENT_FRAGn");
  484.     break;
  485. case XML_NOTATION_NODE:
  486.     fprintf(output, "NOTATIONn");
  487.     break;
  488. case XML_DTD_NODE:
  489.     xmlDebugDumpDtd(output, (xmlDtdPtr) node, depth);
  490.     return;
  491. case XML_ELEMENT_DECL:
  492.     xmlDebugDumpElemDecl(output, (xmlElementPtr) node, depth);
  493.     return;
  494. case XML_ATTRIBUTE_DECL:
  495.     xmlDebugDumpAttrDecl(output, (xmlAttributePtr) node, depth);
  496.     return;
  497.         case XML_ENTITY_DECL:
  498.     xmlDebugDumpEntityDecl(output, (xmlEntityPtr) node, depth);
  499.     return;
  500. default:
  501.     fprintf(output, shift);
  502.     fprintf(output, "NODE_%dn", node->type);
  503.     }
  504.     if (node->doc == NULL) {
  505.         fprintf(output, shift);
  506. fprintf(output, "doc == NULL !!!n");
  507.     }
  508.     if (node->nsDef != NULL) 
  509.         xmlDebugDumpNamespaceList(output, node->nsDef, depth + 1);
  510.     if (node->properties != NULL)
  511. xmlDebugDumpAttrList(output, node->properties, depth + 1);
  512.     if (node->type != XML_ENTITY_REF_NODE) {
  513. if (node->content != NULL) {
  514.     fprintf(output, shift);
  515.     fprintf(output, "content=");
  516. #ifndef XML_USE_BUFFER_CONTENT     
  517.     xmlDebugDumpString(output, node->content);
  518. #else
  519.     xmlDebugDumpString(output, xmlBufferContent(node->content));
  520. #endif
  521.     fprintf(output, "n");
  522. }
  523.     } else {
  524.         xmlEntityPtr ent;
  525. ent = xmlGetDocEntity(node->doc, node->name);
  526. if (ent != NULL)
  527.     xmlDebugDumpEntity(output, ent, depth + 1);
  528.     }
  529.     /*
  530.      * Do a bit of checking
  531.      */
  532.     if (node->parent == NULL)
  533. fprintf(output, "PBM: Node has no parentn");
  534.     if (node->doc == NULL)
  535. fprintf(output, "PBM: Node has no docn");
  536.     if ((node->parent != NULL) && (node->doc != node->parent->doc))
  537. fprintf(output, "PBM: Node doc differs from parent's onen");
  538.     if (node->prev == NULL) {
  539. if ((node->parent != NULL) && (node->parent->children != node))
  540.     fprintf(output, "PBM: Node has no prev and not first of listn");
  541.     } else {
  542. if (node->prev->next != node)
  543.     fprintf(output, "PBM: Node prev->next : back link wrongn");
  544.     }
  545.     if (node->next == NULL) {
  546. if ((node->parent != NULL) && (node->parent->last != node))
  547.     fprintf(output, "PBM: Node has no next and not last of listn");
  548.     } else {
  549. if (node->next->prev != node)
  550.     fprintf(output, "PBM: Node next->prev : forward link wrongn");
  551.     }
  552. }
  553. void xmlDebugDumpNode(FILE *output, xmlNodePtr node, int depth) {
  554.     xmlDebugDumpOneNode(output, node, depth);
  555.     if (node->children != NULL)
  556. xmlDebugDumpNodeList(output, node->children, depth + 1);
  557. }
  558. void xmlDebugDumpNodeList(FILE *output, xmlNodePtr node, int depth) {
  559.     while (node != NULL) {
  560.         xmlDebugDumpNode(output, node, depth);
  561. node = node->next;
  562.     }
  563. }
  564. void xmlDebugDumpDocumentHead(FILE *output, xmlDocPtr doc) {
  565.     if (output == NULL) output = stdout;
  566.     if (doc == NULL) {
  567.         fprintf(output, "DOCUMENT == NULL !n");
  568. return;
  569.     }
  570.     switch (doc->type) {
  571. case XML_ELEMENT_NODE:
  572.     fprintf(output, "Error, ELEMENT found here ");
  573.     break;
  574. case XML_ATTRIBUTE_NODE:
  575.     fprintf(output, "Error, ATTRIBUTE found heren");
  576.     break;
  577. case XML_TEXT_NODE:
  578.     fprintf(output, "Error, TEXTn");
  579.     break;
  580. case XML_CDATA_SECTION_NODE:
  581.     fprintf(output, "Error, CDATA_SECTIONn");
  582.     break;
  583. case XML_ENTITY_REF_NODE:
  584.     fprintf(output, "Error, ENTITY_REFn");
  585.     break;
  586. case XML_ENTITY_NODE:
  587.     fprintf(output, "Error, ENTITYn");
  588.     break;
  589. case XML_PI_NODE:
  590.     fprintf(output, "Error, PIn");
  591.     break;
  592. case XML_COMMENT_NODE:
  593.     fprintf(output, "Error, COMMENTn");
  594.     break;
  595. case XML_DOCUMENT_NODE:
  596.     fprintf(output, "DOCUMENTn");
  597.     break;
  598. case XML_HTML_DOCUMENT_NODE:
  599.     fprintf(output, "HTML DOCUMENTn");
  600.     break;
  601. case XML_DOCUMENT_TYPE_NODE:
  602.     fprintf(output, "Error, DOCUMENT_TYPEn");
  603.     break;
  604. case XML_DOCUMENT_FRAG_NODE:
  605.     fprintf(output, "Error, DOCUMENT_FRAGn");
  606.     break;
  607. case XML_NOTATION_NODE:
  608.     fprintf(output, "Error, NOTATIONn");
  609.     break;
  610. default:
  611.     fprintf(output, "NODE_%dn", doc->type);
  612.     }
  613.     if (doc->name != NULL) {
  614. fprintf(output, "name=");
  615.         xmlDebugDumpString(output, BAD_CAST doc->name);
  616. fprintf(output, "n");
  617.     }
  618.     if (doc->version != NULL) {
  619. fprintf(output, "version=");
  620.         xmlDebugDumpString(output, doc->version);
  621. fprintf(output, "n");
  622.     }
  623.     if (doc->encoding != NULL) {
  624. fprintf(output, "encoding=");
  625.         xmlDebugDumpString(output, doc->encoding);
  626. fprintf(output, "n");
  627.     }
  628.     if (doc->standalone)
  629.         fprintf(output, "standalone=truen");
  630.     if (doc->oldNs != NULL) 
  631.         xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
  632. }
  633. void xmlDebugDumpDocument(FILE *output, xmlDocPtr doc) {
  634.     if (output == NULL) output = stdout;
  635.     if (doc == NULL) {
  636.         fprintf(output, "DOCUMENT == NULL !n");
  637. return;
  638.     }
  639.     xmlDebugDumpDocumentHead(output, doc);
  640.     if (((doc->type == XML_DOCUMENT_NODE) ||
  641.          (doc->type == XML_HTML_DOCUMENT_NODE)) &&
  642.         (doc->children != NULL))
  643.         xmlDebugDumpNodeList(output, doc->children, 1);
  644. }    
  645. void xmlDebugDumpEntities(FILE *output, xmlDocPtr doc) {
  646.     int i;
  647.     xmlEntityPtr cur;
  648.     if (output == NULL) output = stdout;
  649.     if (doc == NULL) {
  650.         fprintf(output, "DOCUMENT == NULL !n");
  651. return;
  652.     }
  653.     switch (doc->type) {
  654. case XML_ELEMENT_NODE:
  655.     fprintf(output, "Error, ELEMENT found here ");
  656.     break;
  657. case XML_ATTRIBUTE_NODE:
  658.     fprintf(output, "Error, ATTRIBUTE found heren");
  659.     break;
  660. case XML_TEXT_NODE:
  661.     fprintf(output, "Error, TEXTn");
  662.     break;
  663. case XML_CDATA_SECTION_NODE:
  664.     fprintf(output, "Error, CDATA_SECTIONn");
  665.     break;
  666. case XML_ENTITY_REF_NODE:
  667.     fprintf(output, "Error, ENTITY_REFn");
  668.     break;
  669. case XML_ENTITY_NODE:
  670.     fprintf(output, "Error, ENTITYn");
  671.     break;
  672. case XML_PI_NODE:
  673.     fprintf(output, "Error, PIn");
  674.     break;
  675. case XML_COMMENT_NODE:
  676.     fprintf(output, "Error, COMMENTn");
  677.     break;
  678. case XML_DOCUMENT_NODE:
  679.     fprintf(output, "DOCUMENTn");
  680.     break;
  681. case XML_HTML_DOCUMENT_NODE:
  682.     fprintf(output, "HTML DOCUMENTn");
  683.     break;
  684. case XML_DOCUMENT_TYPE_NODE:
  685.     fprintf(output, "Error, DOCUMENT_TYPEn");
  686.     break;
  687. case XML_DOCUMENT_FRAG_NODE:
  688.     fprintf(output, "Error, DOCUMENT_FRAGn");
  689.     break;
  690. case XML_NOTATION_NODE:
  691.     fprintf(output, "Error, NOTATIONn");
  692.     break;
  693. default:
  694.     fprintf(output, "NODE_%dn", doc->type);
  695.     }
  696.     if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
  697.         xmlEntitiesTablePtr table = (xmlEntitiesTablePtr) 
  698.                             doc->intSubset->entities;
  699. fprintf(output, "Entities in internal subsetn");
  700. for (i = 0;i < table->nb_entities;i++) {
  701.     cur = table->table[i];
  702.     fprintf(output, "%d : %s : ", i, cur->name);
  703.     switch (cur->etype) {
  704. case XML_INTERNAL_GENERAL_ENTITY:
  705.     fprintf(output, "INTERNAL GENERAL, ");
  706.     break;
  707. case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
  708.     fprintf(output, "EXTERNAL PARSED, ");
  709.     break;
  710. case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
  711.     fprintf(output, "EXTERNAL UNPARSED, ");
  712.     break;
  713. case XML_INTERNAL_PARAMETER_ENTITY:
  714.     fprintf(output, "INTERNAL PARAMETER, ");
  715.     break;
  716. case XML_EXTERNAL_PARAMETER_ENTITY:
  717.     fprintf(output, "EXTERNAL PARAMETER, ");
  718.     break;
  719. default:
  720.     fprintf(output, "UNKNOWN TYPE %d",
  721.     cur->etype);
  722.     }
  723.     if (cur->ExternalID != NULL) 
  724.         fprintf(output, "ID "%s"", cur->ExternalID);
  725.     if (cur->SystemID != NULL)
  726.         fprintf(output, "SYSTEM "%s"", cur->SystemID);
  727.     if (cur->orig != NULL)
  728.         fprintf(output, "n orig "%s"", cur->orig);
  729.     if (cur->content != NULL)
  730.         fprintf(output, "n content "%s"", cur->content);
  731.     fprintf(output, "n");
  732. }
  733.     } else
  734. fprintf(output, "No entities in internal subsetn");
  735.     if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
  736.         xmlEntitiesTablePtr table = (xmlEntitiesTablePtr) 
  737.                             doc->extSubset->entities;
  738. fprintf(output, "Entities in external subsetn");
  739. for (i = 0;i < table->nb_entities;i++) {
  740.     cur = table->table[i];
  741.     fprintf(output, "%d : %s : ", i, cur->name);
  742.     switch (cur->etype) {
  743. case XML_INTERNAL_GENERAL_ENTITY:
  744.     fprintf(output, "INTERNAL GENERAL, ");
  745.     break;
  746. case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
  747.     fprintf(output, "EXTERNAL PARSED, ");
  748.     break;
  749. case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
  750.     fprintf(output, "EXTERNAL UNPARSED, ");
  751.     break;
  752. case XML_INTERNAL_PARAMETER_ENTITY:
  753.     fprintf(output, "INTERNAL PARAMETER, ");
  754.     break;
  755. case XML_EXTERNAL_PARAMETER_ENTITY:
  756.     fprintf(output, "EXTERNAL PARAMETER, ");
  757.     break;
  758. default:
  759.     fprintf(output, "UNKNOWN TYPE %d",
  760.     cur->etype);
  761.     }
  762.     if (cur->ExternalID != NULL) 
  763.         fprintf(output, "ID "%s"", cur->ExternalID);
  764.     if (cur->SystemID != NULL)
  765.         fprintf(output, "SYSTEM "%s"", cur->SystemID);
  766.     if (cur->orig != NULL)
  767.         fprintf(output, "n orig "%s"", cur->orig);
  768.     if (cur->content != NULL)
  769.         fprintf(output, "n content "%s"", cur->content);
  770.     fprintf(output, "n");
  771. }
  772.     } else
  773. fprintf(output, "No entities in external subsetn");
  774. }
  775. static int xmlLsCountNode(xmlNodePtr node) {
  776.     int ret = 0;
  777.     xmlNodePtr list = NULL;
  778.     switch (node->type) {
  779. case XML_ELEMENT_NODE:
  780.     list = node->children;
  781.     break;
  782. case XML_DOCUMENT_NODE:
  783. case XML_HTML_DOCUMENT_NODE:
  784.     list = ((xmlDocPtr) node)->children;
  785.     break;
  786. case XML_ATTRIBUTE_NODE:
  787.     list = ((xmlAttrPtr) node)->children;
  788.     break;
  789. case XML_TEXT_NODE:
  790. case XML_CDATA_SECTION_NODE:
  791. case XML_PI_NODE:
  792. case XML_COMMENT_NODE:
  793.     if (node->content != NULL) {
  794. #ifndef XML_USE_BUFFER_CONTENT     
  795. ret = xmlStrlen(node->content);
  796. #else
  797. ret = xmlBufferLength(node->content);
  798. #endif
  799.             }
  800.     break;
  801. case XML_ENTITY_REF_NODE:
  802. case XML_DOCUMENT_TYPE_NODE:
  803. case XML_ENTITY_NODE:
  804. case XML_DOCUMENT_FRAG_NODE:
  805. case XML_NOTATION_NODE:
  806. case XML_DTD_NODE:
  807.         case XML_ELEMENT_DECL:
  808.         case XML_ATTRIBUTE_DECL:
  809.         case XML_ENTITY_DECL:
  810.     ret = 1;
  811.     break;
  812.     }
  813.     for (;list != NULL;ret++) 
  814.         list = list->next;
  815.     return(ret);
  816. }
  817. void xmlLsOneNode(FILE *output, xmlNodePtr node) {
  818.     switch (node->type) {
  819. case XML_ELEMENT_NODE:
  820.     fprintf(output, "-");
  821.     break;
  822. case XML_ATTRIBUTE_NODE:
  823.     fprintf(output, "a");
  824.     break;
  825. case XML_TEXT_NODE:
  826.     fprintf(output, "t");
  827.     break;
  828. case XML_CDATA_SECTION_NODE:
  829.     fprintf(output, "c");
  830.     break;
  831. case XML_ENTITY_REF_NODE:
  832.     fprintf(output, "e");
  833.     break;
  834. case XML_ENTITY_NODE:
  835.     fprintf(output, "E");
  836.     break;
  837. case XML_PI_NODE:
  838.     fprintf(output, "p");
  839.     break;
  840. case XML_COMMENT_NODE:
  841.     fprintf(output, "c");
  842.     break;
  843. case XML_DOCUMENT_NODE:
  844.     fprintf(output, "d");
  845.     break;
  846. case XML_HTML_DOCUMENT_NODE:
  847.     fprintf(output, "h");
  848.     break;
  849. case XML_DOCUMENT_TYPE_NODE:
  850.     fprintf(output, "T");
  851.     break;
  852. case XML_DOCUMENT_FRAG_NODE:
  853.     fprintf(output, "F");
  854.     break;
  855. case XML_NOTATION_NODE:
  856.     fprintf(output, "N");
  857.     break;
  858. default:
  859.     fprintf(output, "?");
  860.     }
  861.     if (node->properties != NULL)
  862. fprintf(output, "a");
  863.     else
  864. fprintf(output, "-");
  865.     if (node->nsDef != NULL) 
  866. fprintf(output, "n");
  867.     else
  868. fprintf(output, "-");
  869.     fprintf(output, " %8d ", xmlLsCountNode(node));
  870.     switch (node->type) {
  871. case XML_ELEMENT_NODE:
  872.     if (node->name != NULL)
  873. fprintf(output, "%s", node->name);
  874.     break;
  875. case XML_ATTRIBUTE_NODE:
  876.     if (node->name != NULL)
  877. fprintf(output, "%s", node->name);
  878.     break;
  879. case XML_TEXT_NODE:
  880.     if (node->content != NULL) {
  881. #ifndef XML_USE_BUFFER_CONTENT     
  882. xmlDebugDumpString(output, node->content);
  883. #else
  884. xmlDebugDumpString(output, xmlBufferContent(node->content));
  885. #endif
  886.             }
  887.     break;
  888. case XML_CDATA_SECTION_NODE:
  889.     break;
  890. case XML_ENTITY_REF_NODE:
  891.     if (node->name != NULL)
  892. fprintf(output, "%s", node->name);
  893.     break;
  894. case XML_ENTITY_NODE:
  895.     if (node->name != NULL)
  896. fprintf(output, "%s", node->name);
  897.     break;
  898. case XML_PI_NODE:
  899.     if (node->name != NULL)
  900. fprintf(output, "%s", node->name);
  901.     break;
  902. case XML_COMMENT_NODE:
  903.     break;
  904. case XML_DOCUMENT_NODE:
  905.     break;
  906. case XML_HTML_DOCUMENT_NODE:
  907.     break;
  908. case XML_DOCUMENT_TYPE_NODE:
  909.     break;
  910. case XML_DOCUMENT_FRAG_NODE:
  911.     break;
  912. case XML_NOTATION_NODE:
  913.     break;
  914. default:
  915.     if (node->name != NULL)
  916. fprintf(output, "%s", node->name);
  917.     }
  918.     fprintf(output, "n");
  919. }
  920. /****************************************************************
  921.  * *
  922.  *   The XML shell related functions *
  923.  * *
  924.  ****************************************************************/
  925. /*
  926.  * TODO: Improvement/cleanups for the XML shell
  927.  *     - allow to shell out an editor on a subpart
  928.  *     - cleanup function registrations (with help) and calling
  929.  *     - provide registration routines
  930.  */
  931. /**
  932.  * xmlShellList:
  933.  * @ctxt:  the shell context
  934.  * @arg:  unused
  935.  * @node:  a node
  936.  * @node2:  unused
  937.  *
  938.  * Implements the XML shell function "ls"
  939.  * Does an Unix like listing of the given node (like a directory)
  940.  *
  941.  * Returns 0
  942.  */
  943. int
  944. xmlShellList(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
  945.                   xmlNodePtr node2) {
  946.     xmlNodePtr cur;
  947.     if ((node->type == XML_DOCUMENT_NODE) ||
  948.         (node->type == XML_HTML_DOCUMENT_NODE)) {
  949.         cur = ((xmlDocPtr) node)->children;
  950.     } else if (node->children != NULL) {
  951.         cur = node->children;
  952.     } else {
  953. xmlLsOneNode(stdout, node);
  954.         return(0);
  955.     }
  956.     while (cur != NULL) {
  957. xmlLsOneNode(stdout, cur);
  958. cur = cur->next;
  959.     }
  960.     return(0);
  961. }
  962. /**
  963.  * xmlShellDir:
  964.  * @ctxt:  the shell context
  965.  * @arg:  unused
  966.  * @node:  a node
  967.  * @node2:  unused
  968.  *
  969.  * Implements the XML shell function "dir"
  970.  * dumps informations about the node (namespace, attributes, content).
  971.  *
  972.  * Returns 0
  973.  */
  974. int
  975. xmlShellDir(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
  976.                   xmlNodePtr node2) {
  977.     if ((node->type == XML_DOCUMENT_NODE) ||
  978.         (node->type == XML_HTML_DOCUMENT_NODE)) {
  979. xmlDebugDumpDocumentHead(stdout, (xmlDocPtr) node);
  980.     } else if (node->type == XML_ATTRIBUTE_NODE) {
  981. xmlDebugDumpAttr(stdout, (xmlAttrPtr) node, 0);
  982.     } else {
  983. xmlDebugDumpOneNode(stdout, node, 0);
  984.     }
  985.     return(0);
  986. }
  987. /**
  988.  * xmlShellCat:
  989.  * @ctxt:  the shell context
  990.  * @arg:  unused
  991.  * @node:  a node
  992.  * @node2:  unused
  993.  *
  994.  * Implements the XML shell function "cat"
  995.  * dumps the serialization node content (XML or HTML).
  996.  *
  997.  * Returns 0
  998.  */
  999. int
  1000. xmlShellCat(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
  1001.                   xmlNodePtr node2) {
  1002.     if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
  1003. #ifdef LIBXML_HTML_ENABLED
  1004. if (node->type == XML_HTML_DOCUMENT_NODE)
  1005.     htmlDocDump(stdout, (htmlDocPtr) node);
  1006. else
  1007.     htmlNodeDumpFile(stdout, ctxt->doc, node);
  1008. #else
  1009. if (node->type == XML_DOCUMENT_NODE)
  1010.     xmlDocDump(stdout, (xmlDocPtr) node);
  1011. else
  1012.     xmlElemDump(stdout, ctxt->doc, node);
  1013. #endif /* LIBXML_HTML_ENABLED */
  1014.     } else {
  1015. if (node->type == XML_DOCUMENT_NODE)
  1016.     xmlDocDump(stdout, (xmlDocPtr) node);
  1017. else
  1018.     xmlElemDump(stdout, ctxt->doc, node);
  1019.     }
  1020.     printf("n");
  1021.     return(0);
  1022. }
  1023. /**
  1024.  * xmlShellLoad:
  1025.  * @ctxt:  the shell context
  1026.  * @filename:  the file name
  1027.  * @node:  unused
  1028.  * @node2:  unused
  1029.  *
  1030.  * Implements the XML shell function "load"
  1031.  * loads a new document specified by the filename
  1032.  *
  1033.  * Returns 0 or -1 if loading failed
  1034.  */
  1035. int
  1036. xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
  1037.              xmlNodePtr node2) {
  1038.     xmlDocPtr doc;
  1039.     int html = 0;
  1040.     if (ctxt->doc != NULL)
  1041. html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
  1042.     if (html) {
  1043. #ifdef LIBXML_HTML_ENABLED
  1044. doc = htmlParseFile(filename, NULL);
  1045. #else
  1046. printf("HTML support not compiled inn");
  1047. doc = NULL;
  1048. #endif /* LIBXML_HTML_ENABLED */
  1049.     } else {
  1050. doc = xmlParseFile(filename);
  1051.     }
  1052.     if (doc != NULL) {
  1053.         if (ctxt->loaded == 1) {
  1054.     xmlFreeDoc(ctxt->doc);
  1055. }
  1056. ctxt->loaded = 1;
  1057. #ifdef LIBXML_XPATH_ENABLED
  1058. xmlXPathFreeContext(ctxt->pctxt);
  1059. #endif /* LIBXML_XPATH_ENABLED */
  1060. xmlFree(ctxt->filename);
  1061. ctxt->doc = doc;
  1062. ctxt->node = (xmlNodePtr) doc;  
  1063. #ifdef LIBXML_XPATH_ENABLED
  1064. ctxt->pctxt = xmlXPathNewContext(doc);
  1065. #endif /* LIBXML_XPATH_ENABLED */
  1066. ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
  1067.     } else
  1068.         return(-1);
  1069.     return(0);
  1070. }
  1071. /**
  1072.  * xmlShellWrite:
  1073.  * @ctxt:  the shell context
  1074.  * @filename:  the file name
  1075.  * @node:  a node in the tree
  1076.  * @node2:  unused
  1077.  *
  1078.  * Implements the XML shell function "write"
  1079.  * Write the current node to the filename, it saves the serailization
  1080.  * of the subtree under the @node specified
  1081.  *
  1082.  * Returns 0 or -1 in case of error
  1083.  */
  1084. int
  1085. xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
  1086.                   xmlNodePtr node2) {
  1087.     if (node == NULL)
  1088.         return(-1);
  1089.     if ((filename == NULL) || (filename[0] == 0)) {
  1090.         fprintf(stderr, "Write command requires a filename argumentn");
  1091. return(-1);
  1092.     }
  1093. #ifdef W_OK
  1094.     if (access((char *) filename, W_OK)) {
  1095.         fprintf(stderr, "Cannot write to %sn", filename);
  1096. return(-1);
  1097.     }
  1098. #endif    
  1099.     switch(node->type) {
  1100.         case XML_DOCUMENT_NODE:
  1101.     if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
  1102. fprintf(stderr, "Failed to write to %sn", filename);
  1103. return(-1);
  1104.     }
  1105.     break;
  1106.         case XML_HTML_DOCUMENT_NODE:
  1107. #ifdef LIBXML_HTML_ENABLED
  1108.     if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
  1109. fprintf(stderr, "Failed to write to %sn", filename);
  1110. return(-1);
  1111.     }
  1112. #else
  1113.     if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
  1114. fprintf(stderr, "Failed to write to %sn", filename);
  1115. return(-1);
  1116.     }
  1117. #endif /* LIBXML_HTML_ENABLED */
  1118.     break;
  1119. default: {
  1120.     FILE *f;
  1121.     f = fopen((char *) filename, "w");
  1122.     if (f == NULL) {
  1123. fprintf(stderr, "Failed to write to %sn", filename);
  1124. return(-1);
  1125.     }
  1126.     xmlElemDump(f, ctxt->doc, node);
  1127.     fclose(f);
  1128. }
  1129.     }
  1130.     return(0);
  1131. }
  1132. /**
  1133.  * xmlShellSave:
  1134.  * @ctxt:  the shell context
  1135.  * @filename:  the file name (optionnal)
  1136.  * @node:  unused
  1137.  * @node2:  unused
  1138.  *
  1139.  * Implements the XML shell function "save"
  1140.  * Write the current document to the filename, or it's original name
  1141.  *
  1142.  * Returns 0 or -1 in case of error
  1143.  */
  1144. int 
  1145. xmlShellSave(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
  1146.              xmlNodePtr node2) {
  1147.     if (ctxt->doc == NULL)
  1148. return(-1);
  1149.     if ((filename == NULL) || (filename[0] == 0))
  1150.         filename = ctxt->filename;
  1151. #ifdef W_OK
  1152.     if (access((char *) filename, W_OK)) {
  1153.         fprintf(stderr, "Cannot save to %sn", filename);
  1154. return(-1);
  1155.     }
  1156. #endif
  1157.     switch(ctxt->doc->type) {
  1158.         case XML_DOCUMENT_NODE:
  1159.     if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
  1160. fprintf(stderr, "Failed to save to %sn", filename);
  1161.     }
  1162.     break;
  1163.         case XML_HTML_DOCUMENT_NODE:
  1164. #ifdef LIBXML_HTML_ENABLED
  1165.     if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
  1166. fprintf(stderr, "Failed to save to %sn", filename);
  1167.     }
  1168. #else
  1169.     if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
  1170. fprintf(stderr, "Failed to save to %sn", filename);
  1171.     }
  1172. #endif /* LIBXML_HTML_ENABLED */
  1173.     break;
  1174. default:
  1175.     fprintf(stderr, 
  1176.       "To save to subparts of a document use the 'write' commandn");
  1177.     return(-1);
  1178.     
  1179.     }
  1180.     return(0);
  1181. }
  1182. /**
  1183.  * xmlShellValidate:
  1184.  * @ctxt:  the shell context
  1185.  * @dtd:  the DTD URI (optionnal)
  1186.  * @node:  unused
  1187.  * @node2:  unused
  1188.  *
  1189.  * Implements the XML shell function "validate"
  1190.  * Validate the document, if a DTD path is provided, then the validation
  1191.  * is done against the given DTD.
  1192.  *
  1193.  * Returns 0 or -1 in case of error
  1194.  */
  1195. int 
  1196. xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd, xmlNodePtr node,
  1197.                  xmlNodePtr node2) {
  1198.     xmlValidCtxt vctxt;
  1199.     int res = -1;
  1200.     vctxt.userData = stderr;
  1201.     vctxt.error = (xmlValidityErrorFunc) fprintf;
  1202.     vctxt.warning = (xmlValidityWarningFunc) fprintf;
  1203.     if ((dtd == NULL) || (dtd[0] == 0)) {
  1204.         res = xmlValidateDocument(&vctxt, ctxt->doc);
  1205.     } else {
  1206.         xmlDtdPtr subset;
  1207. subset = xmlParseDTD(NULL, (xmlChar *) dtd);
  1208. if (subset != NULL) {
  1209.             res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
  1210.     xmlFreeDtd(subset);
  1211. }
  1212.     }
  1213.     return(res);
  1214. }
  1215. /**
  1216.  * xmlShellDu:
  1217.  * @ctxt:  the shell context
  1218.  * @arg:  unused
  1219.  * @tree:  a node defining a subtree
  1220.  * @node2:  unused
  1221.  *
  1222.  * Implements the XML shell function "du"
  1223.  * show the structure of the subtree under node @tree
  1224.  * If @tree is null, the command works on the current node.
  1225.  *
  1226.  * Returns 0 or -1 in case of error
  1227.  */
  1228. int 
  1229. xmlShellDu(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr tree,
  1230.                   xmlNodePtr node2) {
  1231.     xmlNodePtr node;
  1232.     int indent = 0,i;
  1233.     if (tree == NULL) return(-1);
  1234.     node = tree;
  1235.     while (node != NULL) {
  1236.         if ((node->type == XML_DOCUMENT_NODE) ||
  1237.             (node->type == XML_HTML_DOCUMENT_NODE)) {
  1238.     printf("/n");
  1239. } else if (node->type == XML_ELEMENT_NODE) {
  1240.     for (i = 0;i < indent;i++)
  1241.         printf("  ");
  1242.     printf("%sn", node->name);
  1243. } else {
  1244. }
  1245. /*
  1246.  * Browse the full subtree, deep first
  1247.  */
  1248.         if ((node->type == XML_DOCUMENT_NODE) ||
  1249.             (node->type == XML_HTML_DOCUMENT_NODE)) {
  1250.     node = ((xmlDocPtr) node)->children;
  1251.         } else if (node->children != NULL) {
  1252.     /* deep first */
  1253.     node = node->children;
  1254.     indent++;
  1255. } else if ((node != tree) && (node->next != NULL)) {
  1256.     /* then siblings */
  1257.     node = node->next;
  1258. } else if (node != tree) {
  1259.     /* go up to parents->next if needed */
  1260.     while (node != tree) {
  1261.         if (node->parent != NULL) {
  1262.     node = node->parent;
  1263.     indent--;
  1264. }
  1265. if ((node != tree) && (node->next != NULL)) {
  1266.     node = node->next;
  1267.     break;
  1268. }
  1269. if (node->parent == NULL) {
  1270.     node = NULL;
  1271.     break;
  1272. }
  1273. if (node == tree) {
  1274.     node = NULL;
  1275.     break;
  1276. }
  1277.     }
  1278.     /* exit condition */
  1279.     if (node == tree) 
  1280.         node = NULL;
  1281. } else
  1282.     node = NULL;
  1283.     }
  1284.     return(0);
  1285. }
  1286. /**
  1287.  * xmlShellPwd:
  1288.  * @ctxt:  the shell context
  1289.  * @buffer:  the output buffer
  1290.  * @tree:  a node 
  1291.  * @node2:  unused
  1292.  *
  1293.  * Implements the XML shell function "pwd"
  1294.  * Show the full path from the root to the node, if needed building
  1295.  * thumblers when similar elements exists at a given ancestor level.
  1296.  * The output is compatible with XPath commands.
  1297.  *
  1298.  * Returns 0 or -1 in case of error
  1299.  */
  1300. int 
  1301. xmlShellPwd(xmlShellCtxtPtr ctxt, char *buffer, xmlNodePtr node,
  1302.                   xmlNodePtr node2) {
  1303.     xmlNodePtr cur, tmp, next;
  1304.     char buf[500];
  1305.     char sep;
  1306.     const char *name;
  1307.     int occur = 0;
  1308.     buffer[0] = 0;
  1309.     if (node == NULL) return(-1);
  1310.     cur = node;
  1311.     do {
  1312. name = "";
  1313. sep= '?';
  1314. occur = 0;
  1315. if ((cur->type == XML_DOCUMENT_NODE) ||
  1316.     (cur->type == XML_HTML_DOCUMENT_NODE)) {
  1317.     sep = '/';
  1318.     next = NULL;
  1319. } else if (cur->type == XML_ELEMENT_NODE) {
  1320.     sep = '/';
  1321.     name = (const char *)cur->name;
  1322.     next = cur->parent;
  1323.     /*
  1324.      * Thumbler index computation
  1325.      */
  1326.     tmp = cur->prev;
  1327.             while (tmp != NULL) {
  1328.         if (!xmlStrcmp(cur->name, tmp->name))
  1329.     occur++;
  1330.         tmp = tmp->prev;
  1331.     }
  1332.     if (occur == 0) {
  1333.         tmp = cur->next;
  1334. while (tmp != NULL) {
  1335.     if (!xmlStrcmp(cur->name, tmp->name))
  1336. occur++;
  1337.     tmp = tmp->next;
  1338. }
  1339. if (occur != 0) occur = 1;
  1340.     } else
  1341.         occur++;
  1342. } else if (cur->type == XML_ATTRIBUTE_NODE) {
  1343.     sep = '@';
  1344.     name = (const char *) (((xmlAttrPtr) cur)->name);
  1345.     next = ((xmlAttrPtr) cur)->parent;
  1346. } else {
  1347.     next = cur->parent;
  1348. }
  1349. if (occur == 0)
  1350.     sprintf(buf, "%c%s%s", sep, name, buffer);
  1351. else
  1352.     sprintf(buf, "%c%s[%d]%s", sep, name, occur, buffer);
  1353. strcpy(buffer, buf);
  1354.         cur = next;
  1355.     } while (cur != NULL);
  1356.     return(0);
  1357. }
  1358. /**
  1359.  * xmlShell
  1360.  * @doc:  the initial document
  1361.  * @filename:  the output buffer
  1362.  * @input:  the line reading function
  1363.  * @output:  the output FILE*
  1364.  *
  1365.  * Implements the XML shell 
  1366.  * This allow to load, validate, view, modify and save a document
  1367.  * using a environment similar to a UNIX commandline.
  1368.  */
  1369. void
  1370. xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
  1371.          FILE *output) {
  1372.     char prompt[500] = "/ > ";
  1373.     char *cmdline = NULL;
  1374.     int nbargs;
  1375.     char command[100];
  1376.     char arg[400];
  1377.     xmlShellCtxtPtr ctxt;
  1378.     xmlXPathObjectPtr list;
  1379.     if (doc == NULL)
  1380.         return;
  1381.     if (filename == NULL)
  1382.         return;
  1383.     if (input == NULL)
  1384.         return;
  1385.     if (output == NULL)
  1386.         return;
  1387.     ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
  1388.     if (ctxt == NULL) 
  1389.         return;
  1390.     ctxt->loaded = 0;
  1391.     ctxt->doc = doc;
  1392.     ctxt->input = input;
  1393.     ctxt->output = output;
  1394.     ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
  1395.     ctxt->node = (xmlNodePtr) ctxt->doc;  
  1396. #ifdef LIBXML_XPATH_ENABLED
  1397.     ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
  1398.     if (ctxt->pctxt == NULL) {
  1399. xmlFree(ctxt);
  1400. return;
  1401.     }
  1402. #endif /* LIBXML_XPATH_ENABLED */
  1403.     while (1) {
  1404.         if (ctxt->node == (xmlNodePtr) ctxt->doc)
  1405.     sprintf(prompt, "%s > ", "/");
  1406. else if (ctxt->node->name)
  1407.     sprintf(prompt, "%s > ", ctxt->node->name);
  1408. else
  1409.     sprintf(prompt, "? > ");
  1410.         cmdline = ctxt->input(prompt);
  1411.         if (cmdline == NULL) break;
  1412. command[0] = 0;
  1413. arg[0] = 0;
  1414. nbargs = sscanf(cmdline, "%s %s", command, arg);
  1415. if (command[0] == 0) continue;
  1416.         if (!strcmp(command, "exit"))
  1417.     break;
  1418.         if (!strcmp(command, "quit"))
  1419.     break;
  1420.         if (!strcmp(command, "bye"))
  1421.     break;
  1422. if (!strcmp(command, "validate")) {
  1423.     xmlShellValidate(ctxt, arg, NULL, NULL);
  1424. } else if (!strcmp(command, "load")) {
  1425.     xmlShellLoad(ctxt, arg, NULL, NULL);
  1426. } else if (!strcmp(command, "save")) {
  1427.     xmlShellSave(ctxt, arg, NULL, NULL);
  1428. } else if (!strcmp(command, "write")) {
  1429.     xmlShellWrite(ctxt, arg, NULL, NULL);
  1430. } else if (!strcmp(command, "free")) {
  1431.     if (arg[0] == 0) {
  1432. xmlMemShow(stdout, 0);
  1433.     } else {
  1434.         int len = 0;
  1435. sscanf(arg, "%d", &len);
  1436. xmlMemShow(stdout, len);
  1437.     }
  1438. } else if (!strcmp(command, "pwd")) {
  1439.     char dir[500];
  1440.     if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
  1441. printf("%sn", dir);
  1442. } else  if (!strcmp(command, "du")) {
  1443.     xmlShellDu(ctxt, NULL, ctxt->node, NULL);
  1444. } else  if ((!strcmp(command, "ls")) ||
  1445.       (!strcmp(command, "dir"))) {
  1446.     int dir = (!strcmp(command, "dir"));
  1447.     if (arg[0] == 0) {
  1448. if (dir)
  1449.     xmlShellDir(ctxt, NULL, ctxt->node, NULL);
  1450. else
  1451.     xmlShellList(ctxt, NULL, ctxt->node, NULL);
  1452.     } else {
  1453.         ctxt->pctxt->node = ctxt->node;
  1454. #ifdef LIBXML_XPATH_ENABLED
  1455. if (ctxt->pctxt->nodelist != NULL)
  1456.     xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
  1457.         ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
  1458. list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
  1459. #else
  1460. list = NULL;
  1461. #endif /* LIBXML_XPATH_ENABLED */
  1462. if (list != NULL) {
  1463.     switch (list->type) {
  1464. case XPATH_UNDEFINED:
  1465.     fprintf(stderr, "%s: no such noden", arg);
  1466.     break;
  1467. case XPATH_NODESET: {
  1468.     int i;
  1469.     for (i = 0;i < list->nodesetval->nodeNr;i++) {
  1470. if (dir)
  1471.     xmlShellDir(ctxt, NULL,
  1472.        list->nodesetval->nodeTab[i], NULL);
  1473. else
  1474.     xmlShellList(ctxt, NULL,
  1475.        list->nodesetval->nodeTab[i], NULL);
  1476.     }
  1477.     break;
  1478. }
  1479. case XPATH_BOOLEAN:
  1480.     fprintf(stderr, "%s is a Booleann", arg);
  1481.     break;
  1482. case XPATH_NUMBER:
  1483.     fprintf(stderr, "%s is a numbern", arg);
  1484.     break;
  1485. case XPATH_STRING:
  1486.     fprintf(stderr, "%s is a stringn", arg);
  1487.     break;
  1488.     }
  1489.     xmlXPathFreeNodeSetList(list);
  1490. } else {
  1491.     fprintf(stderr, "%s: no such noden", arg);
  1492. }
  1493. #ifdef LIBXML_XPATH_ENABLED
  1494. if (ctxt->pctxt->nodelist != NULL)
  1495.     xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
  1496. #endif /* LIBXML_XPATH_ENABLED */
  1497. ctxt->pctxt->nodelist = NULL;
  1498.     }
  1499. } else if (!strcmp(command, "cd")) {
  1500.     if (arg[0] == 0) {
  1501. ctxt->node = (xmlNodePtr) ctxt->doc;
  1502.     } else {
  1503.         ctxt->pctxt->node = ctxt->node;
  1504. #ifdef LIBXML_XPATH_ENABLED
  1505. if (ctxt->pctxt->nodelist != NULL)
  1506.     xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
  1507.         ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
  1508. list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
  1509. #else
  1510. list = NULL;
  1511. #endif /* LIBXML_XPATH_ENABLED */
  1512. if (list != NULL) {
  1513.     switch (list->type) {
  1514. case XPATH_UNDEFINED:
  1515.     fprintf(stderr, "%s: no such noden", arg);
  1516.     break;
  1517. case XPATH_NODESET:
  1518.     if (list->nodesetval->nodeNr == 1) {
  1519. ctxt->node = list->nodesetval->nodeTab[0];
  1520.     } else 
  1521. fprintf(stderr, "%s is a %d Node Setn",
  1522.         arg, list->nodesetval->nodeNr);
  1523.     break;
  1524. case XPATH_BOOLEAN:
  1525.     fprintf(stderr, "%s is a Booleann", arg);
  1526.     break;
  1527. case XPATH_NUMBER:
  1528.     fprintf(stderr, "%s is a numbern", arg);
  1529.     break;
  1530. case XPATH_STRING:
  1531.     fprintf(stderr, "%s is a stringn", arg);
  1532.     break;
  1533.     }
  1534.     xmlXPathFreeNodeSetList(list);
  1535. } else {
  1536.     fprintf(stderr, "%s: no such noden", arg);
  1537. }
  1538. #ifdef LIBXML_XPATH_ENABLED
  1539. if (ctxt->pctxt->nodelist != NULL)
  1540.     xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
  1541. #endif /* LIBXML_XPATH_ENABLED */
  1542. ctxt->pctxt->nodelist = NULL;
  1543.     }
  1544. } else if (!strcmp(command, "cat")) {
  1545.     if (arg[0] == 0) {
  1546. xmlShellCat(ctxt, NULL, ctxt->node, NULL);
  1547.     } else {
  1548.         ctxt->pctxt->node = ctxt->node;
  1549. #ifdef LIBXML_XPATH_ENABLED
  1550. if (ctxt->pctxt->nodelist != NULL)
  1551.     xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
  1552.         ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
  1553. list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
  1554. #else
  1555. list = NULL;
  1556. #endif /* LIBXML_XPATH_ENABLED */
  1557. if (list != NULL) {
  1558.     switch (list->type) {
  1559. case XPATH_UNDEFINED:
  1560.     fprintf(stderr, "%s: no such noden", arg);
  1561.     break;
  1562. case XPATH_NODESET: {
  1563.     int i;
  1564.     for (i = 0;i < list->nodesetval->nodeNr;i++) {
  1565.         if (i > 0) printf(" -------n");
  1566. xmlShellCat(ctxt, NULL,
  1567.     list->nodesetval->nodeTab[i], NULL);
  1568.     }
  1569.     break;
  1570. }
  1571. case XPATH_BOOLEAN:
  1572.     fprintf(stderr, "%s is a Booleann", arg);
  1573.     break;
  1574. case XPATH_NUMBER:
  1575.     fprintf(stderr, "%s is a numbern", arg);
  1576.     break;
  1577. case XPATH_STRING:
  1578.     fprintf(stderr, "%s is a stringn", arg);
  1579.     break;
  1580.     }
  1581.     xmlXPathFreeNodeSetList(list);
  1582. } else {
  1583.     fprintf(stderr, "%s: no such noden", arg);
  1584. }
  1585. #ifdef LIBXML_XPATH_ENABLED
  1586. if (ctxt->pctxt->nodelist != NULL)
  1587.     xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
  1588. #endif /* LIBXML_XPATH_ENABLED */
  1589. ctxt->pctxt->nodelist = NULL;
  1590.     }
  1591. } else {
  1592.     fprintf(stderr, "Unknown command %sn", command);
  1593. }
  1594. free(cmdline); /* not xmlFree here ! */
  1595.     }
  1596. #ifdef LIBXML_XPATH_ENABLED
  1597.     xmlXPathFreeContext(ctxt->pctxt);
  1598. #endif /* LIBXML_XPATH_ENABLED */
  1599.     if (ctxt->loaded) {
  1600.         xmlFreeDoc(ctxt->doc);
  1601.     }
  1602.     xmlFree(ctxt);
  1603.     if (cmdline != NULL)
  1604.         free(cmdline); /* not xmlFree here ! */
  1605. }
  1606. #endif /* LIBXML_DEBUG_ENABLED */