?? debugxml.c
字號:
/* * debugXML.c : This is a set of routines used for debugging the tree * produced by the XML parser. * * See Copyright for the status of this software. * * Daniel Veillard <daniel@veillard.com> */#define IN_LIBXML#include "libxml.h"#ifdef LIBXML_DEBUG_ENABLED#include <string.h>#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#ifdef HAVE_STRING_H#include <string.h>#endif#include <libxml/xmlmemory.h>#include <libxml/tree.h>#include <libxml/parser.h>#include <libxml/parserInternals.h>#include <libxml/valid.h>#include <libxml/debugXML.h>#include <libxml/HTMLtree.h>#include <libxml/HTMLparser.h>#include <libxml/xmlerror.h>#include <libxml/globals.h>#include <libxml/xpathInternals.h>#include <libxml/uri.h>#ifdef LIBXML_SCHEMAS_ENABLED#include <libxml/relaxng.h>#endif#define DUMP_TEXT_TYPE 1typedef struct _xmlDebugCtxt xmlDebugCtxt;typedef xmlDebugCtxt *xmlDebugCtxtPtr;struct _xmlDebugCtxt { FILE *output; /* the output file */ char shift[101]; /* used for indenting */ int depth; /* current depth */ xmlDocPtr doc; /* current document */ xmlNodePtr node; /* current node */ xmlDictPtr dict; /* the doc dictionnary */ int check; /* do just checkings */ int errors; /* number of errors found */ int nodict; /* if the document has no dictionnary */ int options; /* options */};static void xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node);static voidxmlCtxtDumpInitCtxt(xmlDebugCtxtPtr ctxt){ int i; ctxt->depth = 0; ctxt->check = 0; ctxt->errors = 0; ctxt->output = stdout; ctxt->doc = NULL; ctxt->node = NULL; ctxt->dict = NULL; ctxt->nodict = 0; ctxt->options = 0; for (i = 0; i < 100; i++) ctxt->shift[i] = ' '; ctxt->shift[100] = 0;}static voidxmlCtxtDumpCleanCtxt(xmlDebugCtxtPtr ctxt ATTRIBUTE_UNUSED){ /* remove the ATTRIBUTE_UNUSED when this is added */}/** * xmlNsCheckScope: * @node: the node * @ns: the namespace node * * Check that a given namespace is in scope on a node. * * Returns 1 if in scope, -1 in case of argument error, * -2 if the namespace is not in scope, and -3 if not on * an ancestor node. */static intxmlNsCheckScope(xmlNodePtr node, xmlNsPtr ns){ xmlNsPtr cur; if ((node == NULL) || (ns == NULL)) return(-1); if ((node->type != XML_ELEMENT_NODE) && (node->type != XML_ATTRIBUTE_NODE) && (node->type != XML_DOCUMENT_NODE) && (node->type != XML_TEXT_NODE) && (node->type != XML_HTML_DOCUMENT_NODE) && (node->type != XML_XINCLUDE_START)) return(-2); while ((node != NULL) && ((node->type == XML_ELEMENT_NODE) || (node->type == XML_ATTRIBUTE_NODE) || (node->type == XML_TEXT_NODE) || (node->type == XML_XINCLUDE_START))) { if ((node->type == XML_ELEMENT_NODE) || (node->type == XML_XINCLUDE_START)) { cur = node->nsDef; while (cur != NULL) { if (cur == ns) return(1); if (xmlStrEqual(cur->prefix, ns->prefix)) return(-2); cur = cur->next; } } node = node->parent; } /* the xml namespace may be declared on the document node */ if ((node != NULL) && ((node->type == XML_DOCUMENT_NODE) || (node->type == XML_HTML_DOCUMENT_NODE))) { xmlNsPtr oldNs = ((xmlDocPtr) node)->oldNs; if (oldNs == ns) return(1); } return(-3);}static voidxmlCtxtDumpSpaces(xmlDebugCtxtPtr ctxt){ if (ctxt->check) return; if ((ctxt->output != NULL) && (ctxt->depth > 0)) { if (ctxt->depth < 50) fprintf(ctxt->output, &ctxt->shift[100 - 2 * ctxt->depth]); else fprintf(ctxt->output, ctxt->shift); }}/** * xmlDebugErr: * @ctxt: a debug context * @error: the error code * * Handle a debug error. */static voidxmlDebugErr(xmlDebugCtxtPtr ctxt, int error, const char *msg){ ctxt->errors++; __xmlRaiseError(NULL, NULL, NULL, NULL, ctxt->node, XML_FROM_CHECK, error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0, msg);}static voidxmlDebugErr2(xmlDebugCtxtPtr ctxt, int error, const char *msg, int extra){ ctxt->errors++; __xmlRaiseError(NULL, NULL, NULL, NULL, ctxt->node, XML_FROM_CHECK, error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0, msg, extra);}static voidxmlDebugErr3(xmlDebugCtxtPtr ctxt, int error, const char *msg, const char *extra){ ctxt->errors++; __xmlRaiseError(NULL, NULL, NULL, NULL, ctxt->node, XML_FROM_CHECK, error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0, msg, extra);}/** * xmlCtxtNsCheckScope: * @ctxt: the debugging context * @node: the node * @ns: the namespace node * * Report if a given namespace is is not in scope. */static voidxmlCtxtNsCheckScope(xmlDebugCtxtPtr ctxt, xmlNodePtr node, xmlNsPtr ns){ int ret; ret = xmlNsCheckScope(node, ns); if (ret == -2) { if (ns->prefix == NULL) xmlDebugErr(ctxt, XML_CHECK_NS_SCOPE, "Reference to default namespace not in scope\n"); else xmlDebugErr3(ctxt, XML_CHECK_NS_SCOPE, "Reference to namespace '%s' not in scope\n", (char *) ns->prefix); } if (ret == -3) { if (ns->prefix == NULL) xmlDebugErr(ctxt, XML_CHECK_NS_ANCESTOR, "Reference to default namespace not on ancestor\n"); else xmlDebugErr3(ctxt, XML_CHECK_NS_ANCESTOR, "Reference to namespace '%s' not on ancestor\n", (char *) ns->prefix); }}/** * xmlCtxtCheckString: * @ctxt: the debug context * @str: the string * * Do debugging on the string, currently it just checks the UTF-8 content */static voidxmlCtxtCheckString(xmlDebugCtxtPtr ctxt, const xmlChar * str){ if (str == NULL) return; if (ctxt->check) { if (!xmlCheckUTF8(str)) { xmlDebugErr3(ctxt, XML_CHECK_NOT_UTF8, "String is not UTF-8 %s", (const char *) str); } }}/** * xmlCtxtCheckName: * @ctxt: the debug context * @name: the name * * Do debugging on the name, for example the dictionnary status and * conformance to the Name production. */static voidxmlCtxtCheckName(xmlDebugCtxtPtr ctxt, const xmlChar * name){ if (ctxt->check) { if (name == NULL) { xmlDebugErr(ctxt, XML_CHECK_NO_NAME, "Name is NULL"); return; } if (xmlValidateName(name, 0)) { xmlDebugErr3(ctxt, XML_CHECK_NOT_NCNAME, "Name is not an NCName '%s'", (const char *) name); } if ((ctxt->dict != NULL) && (!xmlDictOwns(ctxt->dict, name))) { xmlDebugErr3(ctxt, XML_CHECK_OUTSIDE_DICT, "Name is not from the document dictionnary '%s'", (const char *) name); } }}static voidxmlCtxtGenericNodeCheck(xmlDebugCtxtPtr ctxt, xmlNodePtr node) { xmlDocPtr doc; xmlDictPtr dict; doc = node->doc; if (node->parent == NULL) xmlDebugErr(ctxt, XML_CHECK_NO_PARENT, "Node has no parent\n"); if (node->doc == NULL) { xmlDebugErr(ctxt, XML_CHECK_NO_DOC, "Node has no doc\n"); dict = NULL; } else { dict = doc->dict; if ((dict == NULL) && (ctxt->nodict == 0)) {#if 0 /* desactivated right now as it raises too many errors */ if (doc->type == XML_DOCUMENT_NODE) xmlDebugErr(ctxt, XML_CHECK_NO_DICT, "Document has no dictionnary\n");#endif ctxt->nodict = 1; } if (ctxt->doc == NULL) ctxt->doc = doc; if (ctxt->dict == NULL) { ctxt->dict = dict; } } if ((node->parent != NULL) && (node->doc != node->parent->doc) && (!xmlStrEqual(node->name, BAD_CAST "pseudoroot"))) xmlDebugErr(ctxt, XML_CHECK_WRONG_DOC, "Node doc differs from parent's one\n"); if (node->prev == NULL) { if (node->type == XML_ATTRIBUTE_NODE) { if ((node->parent != NULL) && (node != (xmlNodePtr) node->parent->properties)) xmlDebugErr(ctxt, XML_CHECK_NO_PREV, "Attr has no prev and not first of attr list\n"); } else if ((node->parent != NULL) && (node->parent->children != node)) xmlDebugErr(ctxt, XML_CHECK_NO_PREV, "Node has no prev and not first of parent list\n"); } else { if (node->prev->next != node) xmlDebugErr(ctxt, XML_CHECK_WRONG_PREV, "Node prev->next : back link wrong\n"); } if (node->next == NULL) { if ((node->parent != NULL) && (node->type != XML_ATTRIBUTE_NODE) && (node->parent->last != node)) xmlDebugErr(ctxt, XML_CHECK_NO_NEXT, "Node has no next and not last of parent list\n"); } else { if (node->next->prev != node) xmlDebugErr(ctxt, XML_CHECK_WRONG_NEXT, "Node next->prev : forward link wrong\n"); if (node->next->parent != node->parent) xmlDebugErr(ctxt, XML_CHECK_WRONG_PARENT, "Node next->prev : forward link wrong\n"); } if (node->type == XML_ELEMENT_NODE) { xmlNsPtr ns; ns = node->nsDef; while (ns != NULL) { xmlCtxtNsCheckScope(ctxt, node, ns); ns = ns->next; } if (node->ns != NULL) xmlCtxtNsCheckScope(ctxt, node, node->ns); } else if (node->type == XML_ATTRIBUTE_NODE) { if (node->ns != NULL) xmlCtxtNsCheckScope(ctxt, node, node->ns); } if ((node->type != XML_ELEMENT_NODE) && (node->type != XML_ATTRIBUTE_NODE) && (node->type != XML_ELEMENT_DECL) && (node->type != XML_ATTRIBUTE_DECL) && (node->type != XML_DTD_NODE) && (node->type != XML_ELEMENT_DECL) && (node->type != XML_HTML_DOCUMENT_NODE) && (node->type != XML_DOCUMENT_NODE)) { if (node->content != NULL) xmlCtxtCheckString(ctxt, (const xmlChar *) node->content); } switch (node->type) { case XML_ELEMENT_NODE: case XML_ATTRIBUTE_NODE: xmlCtxtCheckName(ctxt, node->name); break; case XML_TEXT_NODE: if ((node->name == xmlStringText) || (node->name == xmlStringTextNoenc)) break; /* some case of entity substitution can lead to this */ if ((ctxt->dict != NULL) && (node->name == xmlDictLookup(ctxt->dict, BAD_CAST "nbktext", 7))) break; xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME, "Text node has wrong name '%s'", (const char *) node->name); break; case XML_COMMENT_NODE: if (node->name == xmlStringComment) break; xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME, "Comment node has wrong name '%s'", (const char *) node->name); break; case XML_PI_NODE: xmlCtxtCheckName(ctxt, node->name); break; case XML_CDATA_SECTION_NODE: if (node->name == NULL) break; xmlDebugErr3(ctxt, XML_CHECK_NAME_NOT_NULL, "CData section has non NULL name '%s'", (const char *) node->name); break; case XML_ENTITY_REF_NODE: case XML_ENTITY_NODE: case XML_DOCUMENT_TYPE_NODE: case XML_DOCUMENT_FRAG_NODE: case XML_NOTATION_NODE: case XML_DTD_NODE: case XML_ELEMENT_DECL: case XML_ATTRIBUTE_DECL: case XML_ENTITY_DECL: case XML_NAMESPACE_DECL: case XML_XINCLUDE_START: case XML_XINCLUDE_END:#ifdef LIBXML_DOCB_ENABLED case XML_DOCB_DOCUMENT_NODE:#endif case XML_DOCUMENT_NODE: case XML_HTML_DOCUMENT_NODE: break; }}static voidxmlCtxtDumpString(xmlDebugCtxtPtr ctxt, const xmlChar * str){ int i; if (ctxt->check) { return; } /* TODO: check UTF8 content of the string */ if (str == NULL) { fprintf(ctxt->output, "(NULL)"); return; } for (i = 0; i < 40; i++) if (str[i] == 0) return; else if (IS_BLANK_CH(str[i])) fputc(' ', ctxt->output); else if (str[i] >= 0x80) fprintf(ctxt->output, "#%X", str[i]); else fputc(str[i], ctxt->output); fprintf(ctxt->output, "...");}static voidxmlCtxtDumpDtdNode(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd){ xmlCtxtDumpSpaces(ctxt); if (dtd == NULL) { if (!ctxt->check) fprintf(ctxt->output, "DTD node is NULL\n"); return; } if (dtd->type != XML_DTD_NODE) { xmlDebugErr(ctxt, XML_CHECK_NOT_DTD, "Node is not a DTD"); return; } if (!ctxt->check) { if (dtd->name != NULL) fprintf(ctxt->output, "DTD(%s)", (char *) dtd->name); else fprintf(ctxt->output, "DTD"); if (dtd->ExternalID != NULL) fprintf(ctxt->output, ", PUBLIC %s", (char *) dtd->ExternalID); if (dtd->SystemID != NULL) fprintf(ctxt->output, ", SYSTEM %s", (char *) dtd->SystemID); fprintf(ctxt->output, "\n"); } /* * Do a bit of checking */ xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) dtd);}static voidxmlCtxtDumpAttrDecl(xmlDebugCtxtPtr ctxt, xmlAttributePtr attr){ xmlCtxtDumpSpaces(ctxt);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -