implemented checks from section 7.2 Daniel
* relaxng.c: implemented checks from section 7.2
Daniel
diff --git a/relaxng.c b/relaxng.c
index b5e50ed..1d3a3f6 100644
--- a/relaxng.c
+++ b/relaxng.c
@@ -80,6 +80,13 @@
XML_RELAXNG_COMBINE_INTERLEAVE /* interleave */
} xmlRelaxNGCombine;
+typedef enum {
+ XML_RELAXNG_CONTENT_ERROR = -1,
+ XML_RELAXNG_CONTENT_EMPTY = 0,
+ XML_RELAXNG_CONTENT_SIMPLE,
+ XML_RELAXNG_CONTENT_COMPLEX
+} xmlRelaxNGContentType;
+
typedef struct _xmlRelaxNGGrammar xmlRelaxNGGrammar;
typedef xmlRelaxNGGrammar *xmlRelaxNGGrammarPtr;
@@ -1956,25 +1963,38 @@
while (content != NULL) {
if (!xmlStrEqual(content->name, BAD_CAST "param"))
break;
- param = xmlRelaxNGNewDefine(ctxt, node);
- if (param != NULL) {
- param->type = XML_RELAXNG_PARAM;
- param->name = xmlGetProp(content, BAD_CAST "name");
- if (param->name == NULL) {
- if (ctxt->error != NULL)
- ctxt->error(ctxt->userData,
- "param has no name\n");
- ctxt->nbErrors++;
+ if (xmlStrEqual(library,
+ BAD_CAST"http://relaxng.org/ns/structure/1.0")) {
+ if (ctxt->error != NULL)
+ ctxt->error(ctxt->userData,
+ "Type library '%s' does not allow type parameters\n",
+ library);
+ ctxt->nbErrors++;
+ content = content->next;
+ while ((content != NULL) &&
+ (xmlStrEqual(content->name, BAD_CAST "param")))
+ content = content->next;
+ } else {
+ param = xmlRelaxNGNewDefine(ctxt, node);
+ if (param != NULL) {
+ param->type = XML_RELAXNG_PARAM;
+ param->name = xmlGetProp(content, BAD_CAST "name");
+ if (param->name == NULL) {
+ if (ctxt->error != NULL)
+ ctxt->error(ctxt->userData,
+ "param has no name\n");
+ ctxt->nbErrors++;
+ }
+ param->value = xmlNodeGetContent(content);
+ if (lastparam == NULL) {
+ def->attrs = lastparam = param;
+ } else {
+ lastparam->next = param;
+ lastparam = param;
+ }
}
- param->value = xmlNodeGetContent(content);
- if (lastparam == NULL) {
- def->attrs = lastparam = param;
- } else {
- lastparam->next = param;
- lastparam = param;
- }
+ content = content->next;
}
- content = content->next;
}
/*
* Handle optional except
@@ -3831,7 +3851,7 @@
}
/**
- * xmlRelaxNGCheckRules:
+ * xmlRelaxNGSimplify:
* @ctxt: a Relax-NG parser context
* @nodes: grammar children nodes
*
@@ -3955,128 +3975,185 @@
}
}
+/**
+ * xmlRelaxNGGroupContentType:
+ * @ct1: the first content type
+ * @ct2: the second content type
+ *
+ * Try to group 2 content types
+ *
+ * Returns the content type
+ */
+static xmlRelaxNGContentType
+xmlRelaxNGGroupContentType(xmlRelaxNGContentType ct1,
+ xmlRelaxNGContentType ct2) {
+ if ((ct1 == XML_RELAXNG_CONTENT_ERROR) ||
+ (ct2 == XML_RELAXNG_CONTENT_ERROR))
+ return(XML_RELAXNG_CONTENT_ERROR);
+ if (ct1 == XML_RELAXNG_CONTENT_EMPTY)
+ return(ct2);
+ if (ct2 == XML_RELAXNG_CONTENT_EMPTY)
+ return(ct1);
+ if ((ct1 == XML_RELAXNG_CONTENT_COMPLEX) &&
+ (ct2 == XML_RELAXNG_CONTENT_COMPLEX))
+ return(XML_RELAXNG_CONTENT_COMPLEX);
+ return(XML_RELAXNG_CONTENT_ERROR);
+}
+
+/**
+ * xmlRelaxNGMaxContentType:
+ * @ct1: the first content type
+ * @ct2: the second content type
+ *
+ * Compute the max content-type
+ *
+ * Returns the content type
+ */
+static xmlRelaxNGContentType
+xmlRelaxNGMaxContentType(xmlRelaxNGContentType ct1,
+ xmlRelaxNGContentType ct2) {
+ if ((ct1 == XML_RELAXNG_CONTENT_ERROR) ||
+ (ct2 == XML_RELAXNG_CONTENT_ERROR))
+ return(XML_RELAXNG_CONTENT_ERROR);
+ if ((ct1 == XML_RELAXNG_CONTENT_SIMPLE) ||
+ (ct2 == XML_RELAXNG_CONTENT_SIMPLE))
+ return(XML_RELAXNG_CONTENT_SIMPLE);
+ if ((ct1 == XML_RELAXNG_CONTENT_COMPLEX) ||
+ (ct2 == XML_RELAXNG_CONTENT_COMPLEX))
+ return(XML_RELAXNG_CONTENT_COMPLEX);
+ return(XML_RELAXNG_CONTENT_EMPTY);
+}
/**
* xmlRelaxNGCheckRules:
* @ctxt: a Relax-NG parser context
- * @nodes: grammar children nodes
+ * @cur: the current definition
* @flags: some accumulated flags
+ * @ptype: the parent type
*
- * Check for rules in section 7
+ * Check for rules in section 7.1 and 7.2
*
- * Returns 0 if check passed, and -1 in case of error
+ * Returns the content type of @cur
*/
-static int
+static xmlRelaxNGContentType
xmlRelaxNGCheckRules(xmlRelaxNGParserCtxtPtr ctxt,
- xmlRelaxNGDefinePtr cur, int flags) {
- int ret = 0, nflags = flags;
+ xmlRelaxNGDefinePtr cur, int flags,
+ xmlRelaxNGType ptype) {
+ int nflags = flags;
+ xmlRelaxNGContentType ret, tmp, val = XML_RELAXNG_CONTENT_EMPTY;
while (cur != NULL) {
+ ret = XML_RELAXNG_CONTENT_EMPTY;
if ((cur->type == XML_RELAXNG_REF) ||
(cur->type == XML_RELAXNG_PARENTREF)) {
+ ret = XML_RELAXNG_CONTENT_COMPLEX;
+
if (flags & XML_RELAXNG_IN_LIST) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern list//ref\n");
ctxt->nbErrors++;
- ret = -1;
}
if (flags & XML_RELAXNG_IN_ATTRIBUTE) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern attribute//ref\n");
ctxt->nbErrors++;
- ret = -1;
}
if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern data/except//ref\n");
ctxt->nbErrors++;
- ret = -1;
}
if (cur->depth != -4) {
cur->depth = -4;
- if (xmlRelaxNGCheckRules(ctxt, cur->content, flags) != 0)
- ret = -1;
+ xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
}
+ if (ret != XML_RELAXNG_CONTENT_ERROR)
+ ret = XML_RELAXNG_CONTENT_COMPLEX;
} else if (cur->type == XML_RELAXNG_ELEMENT) {
if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern data/except//element(ref)\n");
ctxt->nbErrors++;
- ret = -1;
}
if (flags & XML_RELAXNG_IN_LIST) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern list//element(ref)\n");
ctxt->nbErrors++;
- ret = -1;
}
if (flags & XML_RELAXNG_IN_ATTRIBUTE) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern attribute//element(ref)\n");
ctxt->nbErrors++;
- ret = -1;
}
/*
* reset since in the simple form elements are only child
* of grammar/define
*/
nflags = 0;
- if (xmlRelaxNGCheckRules(ctxt, cur->attrs, nflags) != 0)
- ret = -1;
- if (xmlRelaxNGCheckRules(ctxt, cur->content, nflags) != 0)
- ret = -1;
+ ret = xmlRelaxNGCheckRules(ctxt, cur->attrs, nflags, cur->type);
+ if (ret != XML_RELAXNG_CONTENT_EMPTY) {
+ if (ctxt->error != NULL)
+ ctxt->error(ctxt->userData,
+ "Element %s attributes have a content type error\n",
+ cur->name);
+ ctxt->nbErrors++;
+ }
+ ret = xmlRelaxNGCheckRules(ctxt, cur->content, nflags, cur->type);
+ if (ret == XML_RELAXNG_CONTENT_ERROR) {
+ if (ctxt->error != NULL)
+ ctxt->error(ctxt->userData,
+ "Element %s has a content type error\n",
+ cur->name);
+ ctxt->nbErrors++;
+ } else {
+ ret = XML_RELAXNG_CONTENT_COMPLEX;
+ }
} else if (cur->type == XML_RELAXNG_ATTRIBUTE) {
if (flags & XML_RELAXNG_IN_ATTRIBUTE) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern attribute//attribute\n");
ctxt->nbErrors++;
- ret = -1;
}
if (flags & XML_RELAXNG_IN_LIST) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern list//attribute\n");
ctxt->nbErrors++;
- ret = -1;
}
if (flags & XML_RELAXNG_IN_OOMGROUP) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern oneOrMore//group//attribute\n");
ctxt->nbErrors++;
- ret = -1;
}
if (flags & XML_RELAXNG_IN_OOMINTERLEAVE) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern oneOrMore//interleave//attribute\n");
ctxt->nbErrors++;
- ret = -1;
}
if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern data/except//attribute\n");
ctxt->nbErrors++;
- ret = -1;
}
if (flags & XML_RELAXNG_IN_START) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern start//attribute\n");
ctxt->nbErrors++;
- ret = -1;
}
nflags = flags | XML_RELAXNG_IN_ATTRIBUTE;
- if (xmlRelaxNGCheckRules(ctxt, cur->content, nflags) != 0)
- ret = -1;
+ xmlRelaxNGCheckRules(ctxt, cur->content, nflags, cur->type);
+ ret = XML_RELAXNG_CONTENT_EMPTY;
} else if ((cur->type == XML_RELAXNG_ONEORMORE) ||
(cur->type == XML_RELAXNG_ZEROORMORE)) {
if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
@@ -4084,164 +4161,163 @@
ctxt->error(ctxt->userData,
"Found forbidden pattern data/except//oneOrMore\n");
ctxt->nbErrors++;
- ret = -1;
}
if (flags & XML_RELAXNG_IN_START) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern start//oneOrMore\n");
ctxt->nbErrors++;
- ret = -1;
}
nflags = flags | XML_RELAXNG_IN_ONEORMORE;
- if (xmlRelaxNGCheckRules(ctxt, cur->content, nflags) != 0)
- ret = -1;
+ ret = xmlRelaxNGCheckRules(ctxt, cur->content, nflags, cur->type);
+ ret = xmlRelaxNGGroupContentType(ret, ret);
} else if (cur->type == XML_RELAXNG_LIST) {
if (flags & XML_RELAXNG_IN_LIST) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern list//list\n");
ctxt->nbErrors++;
- ret = -1;
}
if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern data/except//list\n");
ctxt->nbErrors++;
- ret = -1;
}
if (flags & XML_RELAXNG_IN_START) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern start//list\n");
ctxt->nbErrors++;
- ret = -1;
}
nflags = flags | XML_RELAXNG_IN_LIST;
- if (xmlRelaxNGCheckRules(ctxt, cur->content, nflags) != 0)
- ret = -1;
+ ret = xmlRelaxNGCheckRules(ctxt, cur->content, nflags, cur->type);
} else if (cur->type == XML_RELAXNG_GROUP) {
if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern data/except//group\n");
ctxt->nbErrors++;
- ret = -1;
}
if (flags & XML_RELAXNG_IN_START) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern start//group\n");
ctxt->nbErrors++;
- ret = -1;
}
if (flags & XML_RELAXNG_IN_ONEORMORE)
nflags = flags | XML_RELAXNG_IN_OOMGROUP;
else
nflags = flags;
- if (xmlRelaxNGCheckRules(ctxt, cur->content, nflags) != 0)
- ret = -1;
+ ret = xmlRelaxNGCheckRules(ctxt, cur->content, nflags, cur->type);
} else if (cur->type == XML_RELAXNG_INTERLEAVE) {
if (flags & XML_RELAXNG_IN_LIST) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern list//interleave\n");
ctxt->nbErrors++;
- ret = -1;
}
if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern data/except//interleave\n");
ctxt->nbErrors++;
- ret = -1;
}
if (flags & XML_RELAXNG_IN_START) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern start//interleave\n");
ctxt->nbErrors++;
- ret = -1;
}
if (flags & XML_RELAXNG_IN_ONEORMORE)
nflags = flags | XML_RELAXNG_IN_OOMINTERLEAVE;
else
nflags = flags;
- if (xmlRelaxNGCheckRules(ctxt, cur->content, nflags) != 0)
- ret = -1;
+ ret = xmlRelaxNGCheckRules(ctxt, cur->content, nflags, cur->type);
} else if (cur->type == XML_RELAXNG_EXCEPT) {
if ((cur->parent != NULL) &&
(cur->parent->type == XML_RELAXNG_DATATYPE))
nflags = flags | XML_RELAXNG_IN_DATAEXCEPT;
else
nflags = flags;
- if (xmlRelaxNGCheckRules(ctxt, cur->content, nflags) != 0)
- ret = -1;
+ ret = xmlRelaxNGCheckRules(ctxt, cur->content, nflags, cur->type);
} else if (cur->type == XML_RELAXNG_DATATYPE) {
if (flags & XML_RELAXNG_IN_START) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern start//data\n");
ctxt->nbErrors++;
- ret = -1;
}
- if (xmlRelaxNGCheckRules(ctxt, cur->content, flags) != 0)
- ret = -1;
+ xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
+ ret = XML_RELAXNG_CONTENT_SIMPLE;
} else if (cur->type == XML_RELAXNG_VALUE) {
if (flags & XML_RELAXNG_IN_START) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern start//value\n");
ctxt->nbErrors++;
- ret = -1;
}
- if (xmlRelaxNGCheckRules(ctxt, cur->content, flags) != 0)
- ret = -1;
+ xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
+ ret = XML_RELAXNG_CONTENT_SIMPLE;
} else if (cur->type == XML_RELAXNG_TEXT) {
if (flags & XML_RELAXNG_IN_LIST) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern list//text\n");
ctxt->nbErrors++;
- ret = -1;
}
if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern data/except//text\n");
ctxt->nbErrors++;
- ret = -1;
}
if (flags & XML_RELAXNG_IN_START) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern start//text\n");
ctxt->nbErrors++;
- ret = -1;
}
+ ret = XML_RELAXNG_CONTENT_COMPLEX;
} else if (cur->type == XML_RELAXNG_EMPTY) {
if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern data/except//empty\n");
ctxt->nbErrors++;
- ret = -1;
}
if (flags & XML_RELAXNG_IN_START) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Found forbidden pattern start//empty\n");
ctxt->nbErrors++;
- ret = -1;
}
+ ret = XML_RELAXNG_CONTENT_EMPTY;
} else {
- if (xmlRelaxNGCheckRules(ctxt, cur->content, flags) != 0)
- ret = -1;
+ ret = xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
}
cur = cur->next;
+ if (ptype == XML_RELAXNG_GROUP) {
+ val = xmlRelaxNGGroupContentType(val, ret);
+ } else if (ptype == XML_RELAXNG_INTERLEAVE) {
+ tmp = xmlRelaxNGGroupContentType(val, ret);
+ if (tmp != XML_RELAXNG_CONTENT_ERROR)
+ tmp = xmlRelaxNGMaxContentType(val, ret);
+ } else if (ptype == XML_RELAXNG_CHOICE) {
+ val = xmlRelaxNGMaxContentType(val, ret);
+ } else if (ptype == XML_RELAXNG_LIST) {
+ val = XML_RELAXNG_CONTENT_SIMPLE;
+ } else if (ptype == XML_RELAXNG_EXCEPT) {
+ if (ret == XML_RELAXNG_CONTENT_ERROR)
+ val = XML_RELAXNG_CONTENT_ERROR;
+ else
+ val = XML_RELAXNG_CONTENT_SIMPLE;
+ } else {
+ val = xmlRelaxNGGroupContentType(val, ret);
+ }
+
}
- return(ret);
+ return(val);
}
/**
@@ -4363,7 +4439,7 @@
(schema->topgrammar->start->next != NULL))
schema->topgrammar->start = schema->topgrammar->start->content;
xmlRelaxNGCheckRules(ctxt, schema->topgrammar->start,
- XML_RELAXNG_IN_START);
+ XML_RELAXNG_IN_START, XML_RELAXNG_NOOP);
}
}