📄 debugxml.c.svn-base
字号:
if (node == NULL) return (-1); if ((filename == NULL) || (filename[0] == 0)) { xmlGenericError(xmlGenericErrorContext, "Write command requires a filename argument\n"); return (-1); }#ifdef W_OK if (access((char *) filename, W_OK)) { xmlGenericError(xmlGenericErrorContext, "Cannot write to %s\n", filename); return (-1); }#endif switch (node->type) { case XML_DOCUMENT_NODE: if (xmlSaveFile((char *) filename, ctxt->doc) < -1) { xmlGenericError(xmlGenericErrorContext, "Failed to write to %s\n", filename); return (-1); } break; case XML_HTML_DOCUMENT_NODE:#ifdef LIBXML_HTML_ENABLED if (htmlSaveFile((char *) filename, ctxt->doc) < 0) { xmlGenericError(xmlGenericErrorContext, "Failed to write to %s\n", filename); return (-1); }#else if (xmlSaveFile((char *) filename, ctxt->doc) < -1) { xmlGenericError(xmlGenericErrorContext, "Failed to write to %s\n", filename); return (-1); }#endif /* LIBXML_HTML_ENABLED */ break; default:{ FILE *f; f = fopen((char *) filename, "w"); if (f == NULL) { xmlGenericError(xmlGenericErrorContext, "Failed to write to %s\n", filename); return (-1); } xmlElemDump(f, ctxt->doc, node); fclose(f); } } return (0);}/** * xmlShellSave: * @ctxt: the shell context * @filename: the file name (optional) * @node: unused * @node2: unused * * Implements the XML shell function "save" * Write the current document to the filename, or it's original name * * Returns 0 or -1 in case of error */intxmlShellSave(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr node2 ATTRIBUTE_UNUSED){ if (ctxt->doc == NULL) return (-1); if ((filename == NULL) || (filename[0] == 0)) filename = ctxt->filename;#ifdef W_OK if (access((char *) filename, W_OK)) { xmlGenericError(xmlGenericErrorContext, "Cannot save to %s\n", filename); return (-1); }#endif switch (ctxt->doc->type) { case XML_DOCUMENT_NODE: if (xmlSaveFile((char *) filename, ctxt->doc) < 0) { xmlGenericError(xmlGenericErrorContext, "Failed to save to %s\n", filename); } break; case XML_HTML_DOCUMENT_NODE:#ifdef LIBXML_HTML_ENABLED if (htmlSaveFile((char *) filename, ctxt->doc) < 0) { xmlGenericError(xmlGenericErrorContext, "Failed to save to %s\n", filename); }#else if (xmlSaveFile((char *) filename, ctxt->doc) < 0) { xmlGenericError(xmlGenericErrorContext, "Failed to save to %s\n", filename); }#endif /* LIBXML_HTML_ENABLED */ break; default: xmlGenericError(xmlGenericErrorContext, "To save to subparts of a document use the 'write' command\n"); return (-1); } return (0);}#endif /* LIBXML_OUTPUT_ENABLED */#ifdef LIBXML_VALID_ENABLED/** * xmlShellValidate: * @ctxt: the shell context * @dtd: the DTD URI (optional) * @node: unused * @node2: unused * * Implements the XML shell function "validate" * Validate the document, if a DTD path is provided, then the validation * is done against the given DTD. * * Returns 0 or -1 in case of error */intxmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd, xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr node2 ATTRIBUTE_UNUSED){ xmlValidCtxt vctxt; int res = -1; vctxt.userData = stderr; vctxt.error = (xmlValidityErrorFunc) fprintf; vctxt.warning = (xmlValidityWarningFunc) fprintf; if ((dtd == NULL) || (dtd[0] == 0)) { res = xmlValidateDocument(&vctxt, ctxt->doc); } else { xmlDtdPtr subset; subset = xmlParseDTD(NULL, (xmlChar *) dtd); if (subset != NULL) { res = xmlValidateDtd(&vctxt, ctxt->doc, subset); xmlFreeDtd(subset); } } return (res);}#endif /* LIBXML_VALID_ENABLED *//** * xmlShellDu: * @ctxt: the shell context * @arg: unused * @tree: a node defining a subtree * @node2: unused * * Implements the XML shell function "du" * show the structure of the subtree under node @tree * If @tree is null, the command works on the current node. * * Returns 0 or -1 in case of error */intxmlShellDu(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree, xmlNodePtr node2 ATTRIBUTE_UNUSED){ xmlNodePtr node; int indent = 0, i; if (!ctxt) return (-1); if (tree == NULL) return (-1); node = tree; while (node != NULL) { if ((node->type == XML_DOCUMENT_NODE) || (node->type == XML_HTML_DOCUMENT_NODE)) { fprintf(ctxt->output, "/\n"); } else if (node->type == XML_ELEMENT_NODE) { for (i = 0; i < indent; i++) fprintf(ctxt->output, " "); fprintf(ctxt->output, "%s\n", node->name); } else { } /* * Browse the full subtree, deep first */ if ((node->type == XML_DOCUMENT_NODE) || (node->type == XML_HTML_DOCUMENT_NODE)) { node = ((xmlDocPtr) node)->children; } else if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) { /* deep first */ node = node->children; indent++; } else if ((node != tree) && (node->next != NULL)) { /* then siblings */ node = node->next; } else if (node != tree) { /* go up to parents->next if needed */ while (node != tree) { if (node->parent != NULL) { node = node->parent; indent--; } if ((node != tree) && (node->next != NULL)) { node = node->next; break; } if (node->parent == NULL) { node = NULL; break; } if (node == tree) { node = NULL; break; } } /* exit condition */ if (node == tree) node = NULL; } else node = NULL; } return (0);}/** * xmlShellPwd: * @ctxt: the shell context * @buffer: the output buffer * @node: a node * @node2: unused * * Implements the XML shell function "pwd" * Show the full path from the root to the node, if needed building * thumblers when similar elements exists at a given ancestor level. * The output is compatible with XPath commands. * * Returns 0 or -1 in case of error */intxmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer, xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED){ xmlChar *path; if (node == NULL) return (-1); path = xmlGetNodePath(node); if (path == NULL) return (-1); /* * This test prevents buffer overflow, because this routine * is only called by xmlShell, in which the second argument is * 500 chars long. * It is a dirty hack before a cleaner solution is found. * Documentation should mention that the second argument must * be at least 500 chars long, and could be stripped if too long. */ _snprintf(buffer, 499, "%s", path); buffer[499] = '0'; xmlFree(path); return (0);}/** * xmlShell: * @doc: the initial document * @filename: the output buffer * @input: the line reading function * @output: the output FILE*, defaults to stdout if NULL * * Implements the XML shell * This allow to load, validate, view, modify and save a document * using a environment similar to a UNIX commandline. */voidxmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, FILE * output){ char prompt[500] = "/ > "; char *cmdline = NULL, *cur; int nbargs; char command[100]; char arg[400]; int i; xmlShellCtxtPtr ctxt; xmlXPathObjectPtr list; if (doc == NULL) return; if (filename == NULL) return; if (input == NULL) return; if (output == NULL) output = stdout; ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt)); if (ctxt == NULL) return; ctxt->loaded = 0; ctxt->doc = doc; ctxt->input = input; ctxt->output = output; ctxt->filename = (char *) xmlStrdup((xmlChar *) filename); ctxt->node = (xmlNodePtr) ctxt->doc;#ifdef LIBXML_XPATH_ENABLED ctxt->pctxt = xmlXPathNewContext(ctxt->doc); if (ctxt->pctxt == NULL) { xmlFree(ctxt); return; }#endif /* LIBXML_XPATH_ENABLED */ while (1) { if (ctxt->node == (xmlNodePtr) ctxt->doc) _snprintf(prompt, sizeof(prompt), "%s > ", "/"); else if ((ctxt->node != NULL) && (ctxt->node->name)) _snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name); else _snprintf(prompt, sizeof(prompt), "? > "); prompt[sizeof(prompt) - 1] = 0; /* * Get a new command line */ cmdline = ctxt->input(prompt); if (cmdline == NULL) break; /* * Parse the command itself */ cur = cmdline; nbargs = 0; while ((*cur == ' ') || (*cur == '\t')) cur++; i = 0; while ((*cur != ' ') && (*cur != '\t') && (*cur != '\n') && (*cur != '\r')) { if (*cur == 0) break; command[i++] = *cur++; } command[i] = 0; if (i == 0) continue; nbargs++; /* * Parse the argument */ while ((*cur == ' ') || (*cur == '\t')) cur++; i = 0; while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) { if (*cur == 0) break; arg[i++] = *cur++; } arg[i] = 0; if (i != 0) nbargs++; /* * start interpreting the command */ if (!strcmp(command, "exit")) break; if (!strcmp(command, "quit")) break; if (!strcmp(command, "bye")) break; if (!strcmp(command, "help")) { fprintf(ctxt->output, "\tbase display XML base of the node\n"); fprintf(ctxt->output, "\tsetbase URI change the XML base of the node\n"); fprintf(ctxt->output, "\tbye leave shell\n"); fprintf(ctxt->output, "\tcat [node] display node or current node\n"); fprintf(ctxt->output, "\tcd [path] change directory to path or to root\n"); fprintf(ctxt->output, "\tdir [path] dumps informations about the node (namespace, attributes, content)\n"); fprintf(ctxt->output, "\tdu [path] show the structure of the subtree under path or the current node\n"); fprintf(ctxt->output, "\texit leave shell\n"); fprintf(ctxt->output, "\thelp display this help\n"); fprintf(ctxt->output, "\tfree display memory usage\n"); fprintf(ctxt->output, "\tload [name] load a new document with name\n"); fprintf(ctxt->output, "\tls [path] list contents of path or the current directory\n");#ifdef LIBXML_XPATH_ENABLED fprintf(ctxt->output, "\txpath expr evaluate the XPath expression in that context and print the result\n");#endif /* LIBXML_XPATH_ENABLED */ fprintf(ctxt->output, "\tpwd display current working directory\n"); fprintf(ctxt->output, "\tquit leave shell\n");#ifdef LIBXML_OUTPUT_ENABLED fprintf(ctxt->output, "\tsave [name] save this document to name or the original name\n"); fprintf(ctxt->output, "\twrite [name] write the current node to the filename\n");#endif /* LIBXML_OUTPUT_ENABLED */#ifdef LIBXML_VALID_ENABLED fprintf(ctxt->output, "\tvalidate check the document for errors\n");#endif /* LIBXML_VALID_ENABLED */#ifdef LIBXML_SCHEMAS_ENABLED fprintf(ctxt->output, "\trelaxng rng validate the document agaisnt the Relax-NG schemas\n");#endif fprintf(ctxt->output, "\tgrep string search for a string in the subtree\n");#ifdef LIBXML_VALID_ENABLED } else if (!strcmp(command, "validate")) { xmlShellValidate(ctxt, arg, NULL, NULL);#endif /* LIBXML_VALID_ENABLED */ } else if (!strcmp(command, "load")) { xmlShellLoad(ctxt, arg, NULL, NULL);#ifdef LIBXML_SCHEMAS_ENABLED } else if (!strcmp(command, "relaxng")) { xmlShellRNGValidate(ctxt, arg, NULL, NULL);#endif#ifdef LIBXML_OUTPUT_ENABLED } else if (!strcmp(command, "save")) { xmlShellSave(ctxt, arg, NULL, NULL); } else if (!strcmp(command, "write")) { xmlShellWrite(ctxt, arg, NULL, NULL);#endif /* LIBXML_OUTPUT_ENABLED */ } else if (!strcmp(command, "grep")) { xmlShellGrep(ctxt, arg, ctxt->node, NULL); } else if (!strcmp(command, "free")) { if (arg[0] == 0) { xmlMemShow(ctxt->output, 0); } else { int len = 0; sscanf(arg, "%d", &len); xmlMemShow(ctxt->output, len); } } else if (!strcmp(command, "pwd")) { char dir[500]; if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL)) fprintf(ctxt->output, "%s\n", dir); } else if (!strcmp(command, "du")) { xmlShellDu(ctxt, NULL, ctxt->node, NULL); } else if (!strcmp(command, "base")) { xmlShellBase(ctxt, NULL, ctxt->node, NULL);#ifdef LIBXML_XPATH_ENABLED } else if (!strcmp(command, "xpath")) { if (arg[0] == 0) { xmlGenericError(xmlGenericErrorContext, "xpath: expression required\n"); } else { ctxt->pctxt->node = ctxt->node; list = xmlXPathEval((xmlChar *) arg, ctxt
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -