added namespace checking daniel
* debugXML.c include/libxml/xmlerror.h: added namespace checking
daniel
diff --git a/debugXML.c b/debugXML.c
index 08364e3..3728470 100644
--- a/debugXML.c
+++ b/debugXML.c
@@ -44,9 +44,6 @@
xmlNodePtr node; /* current node */
int check; /* do just checkings */
int errors; /* number of errors found */
- int nsNr; /* the number of inherited namespaces */
- int nsMax; /* the size of the arrays */
- xmlNsPtr *nsTab; /* the array of namespace nodes */
};
static void xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node);
@@ -57,9 +54,6 @@
int i;
ctxt->depth = 0;
- ctxt->nsNr = 0;
- ctxt->nsMax = 0;
- ctxt->nsTab = NULL;
ctxt->check = 0;
ctxt->errors = 0;
ctxt->output = stdout;
@@ -71,77 +65,64 @@
static void
xmlCtxtDumpCleanCtxt(xmlDebugCtxtPtr ctxt)
{
- if (ctxt->nsTab != NULL)
- xmlFree(ctxt->nsTab);
}
/**
- * xmlNsCheckPush:
- * @ctxt: an XML parser context
- * @ns: the namespace node
+ * xmlNsCheckScope:
+ * @node: the node
+ * @ns: the namespace node
*
- * Pushes a new namespace on top of the ns stack
+ * Check that a given namespace is in scope on a node.
*
- * Returns -1 in case of error, and the index in the stack otherwise.
+ * 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 int
-xmlNsCheckPush(xmlDebugCtxtPtr ctxt, xmlNsPtr ns)
+xmlNsCheckScope(xmlNodePtr node, xmlNsPtr ns)
{
- if (ns == NULL)
- return(ctxt->nsNr);
+ xmlNsPtr cur;
- if ((ctxt->nsMax == 0) || (ctxt->nsTab == NULL)) {
- ctxt->nsMax = 10;
- ctxt->nsNr = 0;
- ctxt->nsTab = (xmlNsPtr *)
- xmlMalloc(ctxt->nsMax * sizeof(ctxt->nsTab[0]));
- if (ctxt->nsTab == NULL) {
- xmlErrMemory(NULL, NULL);
- ctxt->nsMax = 0;
- return (-1);
+ 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;
+ }
}
- } else if (ctxt->nsNr >= ctxt->nsMax) {
- ctxt->nsMax *= 2;
- ctxt->nsTab = (xmlNsPtr *)
- xmlRealloc((char *) ctxt->nsTab,
- ctxt->nsMax * sizeof(ctxt->nsTab[0]));
- if (ctxt->nsTab == NULL) {
- xmlErrMemory(NULL, NULL);
- ctxt->nsMax /= 2;
- return (-1);
- }
+ node = node->parent;
}
- ctxt->nsTab[ctxt->nsNr++] = ns;
- return (ctxt->nsNr);
+ /* 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);
}
-/**
- * xmlNsCheckPop:
- * @ctxt: an XML parser context
- * @nr: the number to pop
- *
- * Pops the top @nr parser prefix/namespace from the ns stack
- *
- * Returns the number of namespaces removed
- */
-static int
-xmlNsCheckPop(xmlDebugCtxtPtr ctxt, int nr)
-{
- int i;
- if (ctxt->nsTab == NULL) return(0);
- if (ctxt->nsNr < nr) {
- xmlGenericError(xmlGenericErrorContext, "Pbm popping %d NS\n", nr);
- nr = ctxt->nsNr;
- }
- if (ctxt->nsNr <= 0)
- return (0);
-
- for (i = 0;i < nr;i++) {
- ctxt->nsNr--;
- ctxt->nsTab[ctxt->nsNr] = NULL;
- }
- return(nr);
-}
static void
xmlCtxtDumpSpaces(xmlDebugCtxtPtr ctxt)
{
@@ -193,6 +174,40 @@
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 void
+xmlCtxtNsCheckScope(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);
+ }
+}
+
static void
xmlCtxtGenericNodeCheck(xmlDebugCtxtPtr ctxt, xmlNodePtr node) {
if (node->parent == NULL)
@@ -229,7 +244,25 @@
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);
+ }
+
}
static void