This is the 2.0.0-beta, lots and lots and lots of changes
Have a look at http://xmlsoft.org/upgrade.html
Daniel
diff --git a/valid.c b/valid.c
index ee4ae22..398fee1 100644
--- a/valid.c
+++ b/valid.c
@@ -25,6 +25,120 @@
#include "parser.h"
#include "parserInternals.h"
+/*
+ * Generic function for accessing stacks in the Validity Context
+ */
+
+#define PUSH_AND_POP(scope, type, name) \
+scope int name##VPush(xmlValidCtxtPtr ctxt, type value) { \
+ if (ctxt->name##Nr >= ctxt->name##Max) { \
+ ctxt->name##Max *= 2; \
+ ctxt->name##Tab = (void *) xmlRealloc(ctxt->name##Tab, \
+ ctxt->name##Max * sizeof(ctxt->name##Tab[0])); \
+ if (ctxt->name##Tab == NULL) { \
+ fprintf(stderr, "realloc failed !\n"); \
+ return(0); \
+ } \
+ } \
+ ctxt->name##Tab[ctxt->name##Nr] = value; \
+ ctxt->name = value; \
+ return(ctxt->name##Nr++); \
+} \
+scope type name##VPop(xmlValidCtxtPtr ctxt) { \
+ type ret; \
+ if (ctxt->name##Nr <= 0) return(0); \
+ ctxt->name##Nr--; \
+ if (ctxt->name##Nr > 0) \
+ ctxt->name = ctxt->name##Tab[ctxt->name##Nr - 1]; \
+ else \
+ ctxt->name = NULL; \
+ ret = ctxt->name##Tab[ctxt->name##Nr]; \
+ ctxt->name##Tab[ctxt->name##Nr] = 0; \
+ return(ret); \
+} \
+
+PUSH_AND_POP(static, xmlNodePtr, node)
+
+/* #define DEBUG_VALID_ALGO */
+
+#ifdef DEBUG_VALID_ALGO
+void xmlValidPrintNodeList(xmlNodePtr cur) {
+ if (cur == NULL)
+ fprintf(stderr, "null ");
+ while (cur != NULL) {
+ switch (cur->type) {
+ case XML_ELEMENT_NODE:
+ fprintf(stderr, "%s ", cur->name);
+ break;
+ case XML_TEXT_NODE:
+ fprintf(stderr, "text ");
+ break;
+ case XML_CDATA_SECTION_NODE:
+ fprintf(stderr, "cdata ");
+ break;
+ case XML_ENTITY_REF_NODE:
+ fprintf(stderr, "&%s; ", cur->name);
+ break;
+ case XML_PI_NODE:
+ fprintf(stderr, "pi(%s) ", cur->name);
+ break;
+ case XML_COMMENT_NODE:
+ fprintf(stderr, "comment ");
+ break;
+ case XML_ATTRIBUTE_NODE:
+ fprintf(stderr, "?attr? ");
+ break;
+ case XML_ENTITY_NODE:
+ fprintf(stderr, "?ent? ");
+ break;
+ case XML_DOCUMENT_NODE:
+ fprintf(stderr, "?doc? ");
+ break;
+ case XML_DOCUMENT_TYPE_NODE:
+ fprintf(stderr, "?doctype? ");
+ break;
+ case XML_DOCUMENT_FRAG_NODE:
+ fprintf(stderr, "?frag? ");
+ break;
+ case XML_NOTATION_NODE:
+ fprintf(stderr, "?nota? ");
+ break;
+ case XML_HTML_DOCUMENT_NODE:
+ fprintf(stderr, "?html? ");
+ break;
+ case XML_DTD_NODE:
+ fprintf(stderr, "?dtd? ");
+ break;
+ case XML_ELEMENT_DECL:
+ fprintf(stderr, "?edecl? ");
+ break;
+ case XML_ATTRIBUTE_DECL:
+ fprintf(stderr, "?adecl? ");
+ break;
+ case XML_ENTITY_DECL:
+ fprintf(stderr, "?entdecl? ");
+ break;
+ }
+ cur = cur->next;
+ }
+}
+
+void xmlValidDebug(xmlNodePtr cur, xmlElementContentPtr cont) {
+ char expr[1000];
+
+ expr[0] = 0;
+ fprintf(stderr, "valid: ");
+ xmlValidPrintNodeList(cur);
+ fprintf(stderr, "against ");
+ xmlSprintfElementContent(expr, cont, 0);
+ fprintf(stderr, "%s\n", expr);
+}
+
+#define DEBUG_VALID_STATE(n,c) xmlValidDebug(n,c);
+#else
+#define DEBUG_VALID_STATE(n,c)
+#endif
+
/* TODO: use hash table for accesses to elem and attribute dedinitions */
#define VERROR \
@@ -310,7 +424,8 @@
*/
xmlElementPtr
xmlAddElementDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name,
- xmlElementTypeVal type, xmlElementContentPtr content) {
+ xmlElementTypeVal type,
+ xmlElementContentPtr content) {
xmlElementPtr ret, cur;
xmlElementTablePtr table;
int i;
@@ -403,17 +518,31 @@
fprintf(stderr, "xmlAddElementDecl: out of memory\n");
return(NULL);
}
+ memset(ret, 0, sizeof(xmlElement));
+ ret->type = XML_ELEMENT_DECL;
table->table[table->nb_elements] = ret;
/*
* fill the structure.
*/
- ret->type = type;
+ ret->etype = type;
ret->name = xmlStrdup(name);
ret->content = xmlCopyElementContent(content);
ret->attributes = xmlScanAttributeDecl(dtd, name);
table->nb_elements++;
+ /*
+ * Link it to the Dtd
+ */
+ ret->parent = dtd;
+ ret->doc = dtd->doc;
+ if (dtd->last == NULL) {
+ dtd->children = dtd->last = (xmlNodePtr) ret;
+ } else {
+ dtd->last->next = (xmlNodePtr) ret;
+ ret->prev = dtd->last;
+ dtd->last = (xmlNodePtr) ret;
+ }
return(ret);
}
@@ -426,6 +555,7 @@
void
xmlFreeElement(xmlElementPtr elem) {
if (elem == NULL) return;
+ xmlUnlinkNode((xmlNodePtr) elem);
xmlFreeElementContent(elem->content);
if (elem->name != NULL)
xmlFree((xmlChar *) elem->name);
@@ -488,9 +618,11 @@
xmlFree(ret->table);
return(NULL);
}
+ memset(cur, 0, sizeof(xmlElement));
+ cur->type = XML_ELEMENT_DECL;
ret->table[i] = cur;
ent = table->table[i];
- cur->type = ent->type;
+ cur->etype = ent->etype;
if (ent->name != NULL)
cur->name = xmlStrdup(ent->name);
else
@@ -503,6 +635,48 @@
}
/**
+ * xmlDumpElementDecl:
+ * @buf: the XML buffer output
+ * @elem: An element table
+ *
+ * This will dump the content of the element declaration as an XML
+ * DTD definition
+ */
+void
+xmlDumpElementDecl(xmlBufferPtr buf, xmlElementPtr elem) {
+ switch (elem->etype) {
+ case XML_ELEMENT_TYPE_EMPTY:
+ xmlBufferWriteChar(buf, "<!ELEMENT ");
+ xmlBufferWriteCHAR(buf, elem->name);
+ xmlBufferWriteChar(buf, " EMPTY>\n");
+ break;
+ case XML_ELEMENT_TYPE_ANY:
+ xmlBufferWriteChar(buf, "<!ELEMENT ");
+ xmlBufferWriteCHAR(buf, elem->name);
+ xmlBufferWriteChar(buf, " ANY>\n");
+ break;
+ case XML_ELEMENT_TYPE_MIXED:
+ xmlBufferWriteChar(buf, "<!ELEMENT ");
+ xmlBufferWriteCHAR(buf, elem->name);
+ xmlBufferWriteChar(buf, " ");
+ xmlDumpElementContent(buf, elem->content, 1);
+ xmlBufferWriteChar(buf, ">\n");
+ break;
+ case XML_ELEMENT_TYPE_ELEMENT:
+ xmlBufferWriteChar(buf, "<!ELEMENT ");
+ xmlBufferWriteCHAR(buf, elem->name);
+ xmlBufferWriteChar(buf, " ");
+ xmlDumpElementContent(buf, elem->content, 1);
+ xmlBufferWriteChar(buf, ">\n");
+ break;
+ default:
+ fprintf(stderr,
+ "xmlDumpElementDecl: internal: unknown type %d\n",
+ elem->etype);
+ }
+}
+
+/**
* xmlDumpElementTable:
* @buf: the XML buffer output
* @table: An element table
@@ -518,36 +692,7 @@
for (i = 0;i < table->nb_elements;i++) {
cur = table->table[i];
- switch (cur->type) {
- case XML_ELEMENT_TYPE_EMPTY:
- xmlBufferWriteChar(buf, "<!ELEMENT ");
- xmlBufferWriteCHAR(buf, cur->name);
- xmlBufferWriteChar(buf, " EMPTY>\n");
- break;
- case XML_ELEMENT_TYPE_ANY:
- xmlBufferWriteChar(buf, "<!ELEMENT ");
- xmlBufferWriteCHAR(buf, cur->name);
- xmlBufferWriteChar(buf, " ANY>\n");
- break;
- case XML_ELEMENT_TYPE_MIXED:
- xmlBufferWriteChar(buf, "<!ELEMENT ");
- xmlBufferWriteCHAR(buf, cur->name);
- xmlBufferWriteChar(buf, " ");
- xmlDumpElementContent(buf, cur->content, 1);
- xmlBufferWriteChar(buf, ">\n");
- break;
- case XML_ELEMENT_TYPE_ELEMENT:
- xmlBufferWriteChar(buf, "<!ELEMENT ");
- xmlBufferWriteCHAR(buf, cur->name);
- xmlBufferWriteChar(buf, " ");
- xmlDumpElementContent(buf, cur->content, 1);
- xmlBufferWriteChar(buf, ">\n");
- break;
- default:
- fprintf(stderr,
- "xmlDumpElementTable: internal: unknown type %d\n",
- cur->type);
- }
+ xmlDumpElementDecl(buf, cur);
}
}
@@ -570,12 +715,10 @@
(long)sizeof(xmlEnumeration));
return(NULL);
}
+ memset(ret, 0, sizeof(xmlEnumeration));
if (name != NULL)
ret->name = xmlStrdup(name);
- else
- ret->name = NULL;
- ret->next = NULL;
return(ret);
}
@@ -701,7 +844,7 @@
for (i = 0;i < table->nb_attributes;i++) {
if (!xmlStrcmp(table->table[i]->elem, elem)) {
- table->table[i]->next = ret;
+ table->table[i]->nexth = ret;
ret = table->table[i];
}
}
@@ -726,14 +869,14 @@
if (elem == NULL) return(0);
cur = elem->attributes;
while (cur != NULL) {
- if (cur->type == XML_ATTRIBUTE_ID) {
+ if (cur->atype == XML_ATTRIBUTE_ID) {
ret ++;
if (ret > 1)
VERROR(ctxt->userData,
"Element %s has too may ID attributes defined : %s\n",
elem->name, cur->name);
}
- cur = cur->next;
+ cur = cur->nexth;
}
return(ret);
}
@@ -745,6 +888,7 @@
* @dtd: pointer to the DTD
* @elem: the element name
* @name: the attribute name
+ * @ns: the attribute namespace prefix
* @type: the attribute type
* @def: the attribute default type
* @defaultValue: the attribute default value
@@ -756,14 +900,12 @@
*/
xmlAttributePtr
xmlAddAttributeDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *elem,
- const xmlChar *name, xmlAttributeType type,
- xmlAttributeDefault def, const xmlChar *defaultValue,
- xmlEnumerationPtr tree) {
+ const xmlChar *name, const xmlChar *ns,
+ xmlAttributeType type, xmlAttributeDefault def,
+ const xmlChar *defaultValue, xmlEnumerationPtr tree) {
xmlAttributePtr ret, cur;
xmlAttributeTablePtr table;
xmlElementPtr elemDef;
- xmlChar *rname;
- xmlChar *ns;
int i;
if (dtd == NULL) {
@@ -825,11 +967,6 @@
}
/*
- * Split the full name into a namespace prefix and the tag name
- */
- rname = xmlSplitQName(name, &ns);
-
- /*
* Validity Check:
* Search the DTD for previous declarations of the ATTLIST
*/
@@ -837,12 +974,12 @@
cur = table->table[i];
if ((ns != NULL) && (cur->prefix == NULL)) continue;
if ((ns == NULL) && (cur->prefix != NULL)) continue;
- if ((!xmlStrcmp(cur->name, rname)) && (!xmlStrcmp(cur->elem, elem)) &&
+ if ((!xmlStrcmp(cur->name, name)) && (!xmlStrcmp(cur->elem, elem)) &&
((ns == NULL) || (!xmlStrcmp(cur->prefix, ns)))) {
/*
* The attribute is already defined in this Dtd.
*/
- VERROR(ctxt->userData, "Attribute %s on %s: already defined\n",
+ VWARNING(ctxt->userData, "Attribute %s on %s: already defined\n",
elem, name);
}
}
@@ -868,21 +1005,21 @@
fprintf(stderr, "xmlAddAttributeDecl: out of memory\n");
return(NULL);
}
+ memset(ret, 0, sizeof(xmlAttribute));
+ ret->type = XML_ATTRIBUTE_DECL;
table->table[table->nb_attributes] = ret;
/*
* fill the structure.
*/
- ret->type = type;
- ret->name = rname;
- ret->prefix = ns;
+ ret->atype = type;
+ ret->name = xmlStrdup(name);
+ ret->prefix = xmlStrdup(ns);
ret->elem = xmlStrdup(elem);
ret->def = def;
ret->tree = tree;
if (defaultValue != NULL)
ret->defaultValue = xmlStrdup(defaultValue);
- else
- ret->defaultValue = NULL;
elemDef = xmlGetDtdElementDesc(dtd, elem);
if (elemDef != NULL) {
if ((type == XML_ATTRIBUTE_ID) &&
@@ -890,11 +1027,23 @@
VERROR(ctxt->userData,
"Element %s has too may ID attributes defined : %s\n",
elem, name);
- ret->next = elemDef->attributes;
+ ret->nexth = elemDef->attributes;
elemDef->attributes = ret;
}
table->nb_attributes++;
+ /*
+ * Link it to the Dtd
+ */
+ ret->parent = dtd;
+ ret->doc = dtd->doc;
+ if (dtd->last == NULL) {
+ dtd->children = dtd->last = (xmlNodePtr) ret;
+ } else {
+ dtd->last->next = (xmlNodePtr) ret;
+ ret->prev = dtd->last;
+ dtd->last = (xmlNodePtr) ret;
+ }
return(ret);
}
@@ -907,6 +1056,7 @@
void
xmlFreeAttribute(xmlAttributePtr attr) {
if (attr == NULL) return;
+ xmlUnlinkNode((xmlNodePtr) attr);
if (attr->tree != NULL)
xmlFreeEnumeration(attr->tree);
if (attr->elem != NULL)
@@ -977,28 +1127,100 @@
xmlFree(ret->table);
return(NULL);
}
+ memset(cur, 0, sizeof(xmlAttribute));
+ /* !!! cur->type = XML_ATTRIBUTE_DECL; */
ret->table[i] = cur;
- cur->type = attr->type;
+ cur->atype = attr->atype;
cur->def = attr->def;
cur->tree = xmlCopyEnumeration(attr->tree);
if (attr->elem != NULL)
cur->elem = xmlStrdup(attr->elem);
- else
- cur->elem = NULL;
if (attr->name != NULL)
cur->name = xmlStrdup(attr->name);
- else
- cur->name = NULL;
if (attr->defaultValue != NULL)
cur->defaultValue = xmlStrdup(attr->defaultValue);
- else
- cur->defaultValue = NULL;
/* NEED to rebuild the next chain !!!!!! */
}
return(ret);
}
/**
+ * xmlDumpAttributeDecl:
+ * @buf: the XML buffer output
+ * @attr: An attribute declaration
+ *
+ * This will dump the content of the attribute declaration as an XML
+ * DTD definition
+ */
+void
+xmlDumpAttributeDecl(xmlBufferPtr buf, xmlAttributePtr attr) {
+ xmlBufferWriteChar(buf, "<!ATTLIST ");
+ xmlBufferWriteCHAR(buf, attr->elem);
+ xmlBufferWriteChar(buf, " ");
+ xmlBufferWriteCHAR(buf, attr->name);
+ switch (attr->atype) {
+ case XML_ATTRIBUTE_CDATA:
+ xmlBufferWriteChar(buf, " CDATA");
+ break;
+ case XML_ATTRIBUTE_ID:
+ xmlBufferWriteChar(buf, " ID");
+ break;
+ case XML_ATTRIBUTE_IDREF:
+ xmlBufferWriteChar(buf, " IDREF");
+ break;
+ case XML_ATTRIBUTE_IDREFS:
+ xmlBufferWriteChar(buf, " IDREFS");
+ break;
+ case XML_ATTRIBUTE_ENTITY:
+ xmlBufferWriteChar(buf, " ENTITY");
+ break;
+ case XML_ATTRIBUTE_ENTITIES:
+ xmlBufferWriteChar(buf, " ENTITIES");
+ break;
+ case XML_ATTRIBUTE_NMTOKEN:
+ xmlBufferWriteChar(buf, " NMTOKEN");
+ break;
+ case XML_ATTRIBUTE_NMTOKENS:
+ xmlBufferWriteChar(buf, " NMTOKENS");
+ break;
+ case XML_ATTRIBUTE_ENUMERATION:
+ xmlBufferWriteChar(buf, " (");
+ xmlDumpEnumeration(buf, attr->tree);
+ break;
+ case XML_ATTRIBUTE_NOTATION:
+ xmlBufferWriteChar(buf, " NOTATION (");
+ xmlDumpEnumeration(buf, attr->tree);
+ break;
+ default:
+ fprintf(stderr,
+ "xmlDumpAttributeTable: internal: unknown type %d\n",
+ attr->atype);
+ }
+ switch (attr->def) {
+ case XML_ATTRIBUTE_NONE:
+ break;
+ case XML_ATTRIBUTE_REQUIRED:
+ xmlBufferWriteChar(buf, " #REQUIRED");
+ break;
+ case XML_ATTRIBUTE_IMPLIED:
+ xmlBufferWriteChar(buf, " #IMPLIED");
+ break;
+ case XML_ATTRIBUTE_FIXED:
+ xmlBufferWriteChar(buf, " #FIXED");
+ break;
+ default:
+ fprintf(stderr,
+ "xmlDumpAttributeTable: internal: unknown default %d\n",
+ attr->def);
+ }
+ if (attr->defaultValue != NULL) {
+ xmlBufferWriteChar(buf, " ");
+ xmlBufferWriteQuotedString(buf, attr->defaultValue);
+ }
+ xmlBufferWriteChar(buf, ">\n");
+}
+
+/**
* xmlDumpAttributeTable:
* @buf: the XML buffer output
* @table: An attribute table
@@ -1014,70 +1236,7 @@
for (i = 0;i < table->nb_attributes;i++) {
cur = table->table[i];
- xmlBufferWriteChar(buf, "<!ATTLIST ");
- xmlBufferWriteCHAR(buf, cur->elem);
- xmlBufferWriteChar(buf, " ");
- xmlBufferWriteCHAR(buf, cur->name);
- switch (cur->type) {
- case XML_ATTRIBUTE_CDATA:
- xmlBufferWriteChar(buf, " CDATA");
- break;
- case XML_ATTRIBUTE_ID:
- xmlBufferWriteChar(buf, " ID");
- break;
- case XML_ATTRIBUTE_IDREF:
- xmlBufferWriteChar(buf, " IDREF");
- break;
- case XML_ATTRIBUTE_IDREFS:
- xmlBufferWriteChar(buf, " IDREFS");
- break;
- case XML_ATTRIBUTE_ENTITY:
- xmlBufferWriteChar(buf, " ENTITY");
- break;
- case XML_ATTRIBUTE_ENTITIES:
- xmlBufferWriteChar(buf, " ENTITIES");
- break;
- case XML_ATTRIBUTE_NMTOKEN:
- xmlBufferWriteChar(buf, " NMTOKEN");
- break;
- case XML_ATTRIBUTE_NMTOKENS:
- xmlBufferWriteChar(buf, " NMTOKENS");
- break;
- case XML_ATTRIBUTE_ENUMERATION:
- xmlBufferWriteChar(buf, " (");
- xmlDumpEnumeration(buf, cur->tree);
- break;
- case XML_ATTRIBUTE_NOTATION:
- xmlBufferWriteChar(buf, " NOTATION (");
- xmlDumpEnumeration(buf, cur->tree);
- break;
- default:
- fprintf(stderr,
- "xmlDumpAttributeTable: internal: unknown type %d\n",
- cur->type);
- }
- switch (cur->def) {
- case XML_ATTRIBUTE_NONE:
- break;
- case XML_ATTRIBUTE_REQUIRED:
- xmlBufferWriteChar(buf, " #REQUIRED");
- break;
- case XML_ATTRIBUTE_IMPLIED:
- xmlBufferWriteChar(buf, " #IMPLIED");
- break;
- case XML_ATTRIBUTE_FIXED:
- xmlBufferWriteChar(buf, " #FIXED");
- break;
- default:
- fprintf(stderr,
- "xmlDumpAttributeTable: internal: unknown default %d\n",
- cur->def);
- }
- if (cur->defaultValue != NULL) {
- xmlBufferWriteChar(buf, " ");
- xmlBufferWriteQuotedString(buf, cur->defaultValue);
- }
- xmlBufferWriteChar(buf, ">\n");
+ xmlDumpAttributeDecl(buf, cur);
}
}
@@ -1197,6 +1356,7 @@
fprintf(stderr, "xmlAddNotationDecl: out of memory\n");
return(NULL);
}
+ memset(ret, 0, sizeof(xmlNotation));
table->table[table->nb_notations] = ret;
/*
@@ -1205,12 +1365,8 @@
ret->name = xmlStrdup(name);
if (SystemID != NULL)
ret->SystemID = xmlStrdup(SystemID);
- else
- ret->SystemID = NULL;
if (PublicID != NULL)
ret->PublicID = xmlStrdup(PublicID);
- else
- ret->PublicID = NULL;
table->nb_notations++;
return(ret);
@@ -1309,6 +1465,31 @@
}
/**
+ * xmlDumpNotationDecl:
+ * @buf: the XML buffer output
+ * @nota: A notation declaration
+ *
+ * This will dump the content the notation declaration as an XML DTD definition
+ */
+void
+xmlDumpNotationDecl(xmlBufferPtr buf, xmlNotationPtr nota) {
+ xmlBufferWriteChar(buf, "<!NOTATION ");
+ xmlBufferWriteCHAR(buf, nota->name);
+ if (nota->PublicID != NULL) {
+ xmlBufferWriteChar(buf, " PUBLIC ");
+ xmlBufferWriteQuotedString(buf, nota->PublicID);
+ if (nota->SystemID != NULL) {
+ xmlBufferWriteChar(buf, " ");
+ xmlBufferWriteCHAR(buf, nota->SystemID);
+ }
+ } else {
+ xmlBufferWriteChar(buf, " SYSTEM ");
+ xmlBufferWriteCHAR(buf, nota->SystemID);
+ }
+ xmlBufferWriteChar(buf, " >\n");
+}
+
+/**
* xmlDumpNotationTable:
* @buf: the XML buffer output
* @table: A notation table
@@ -1324,20 +1505,7 @@
for (i = 0;i < table->nb_notations;i++) {
cur = table->table[i];
- xmlBufferWriteChar(buf, "<!NOTATION ");
- xmlBufferWriteCHAR(buf, cur->name);
- if (cur->PublicID != NULL) {
- xmlBufferWriteChar(buf, " PUBLIC ");
- xmlBufferWriteQuotedString(buf, cur->PublicID);
- if (cur->SystemID != NULL) {
- xmlBufferWriteChar(buf, " ");
- xmlBufferWriteCHAR(buf, cur->SystemID);
- }
- } else {
- xmlBufferWriteChar(buf, " SYSTEM ");
- xmlBufferWriteCHAR(buf, cur->SystemID);
- }
- xmlBufferWriteChar(buf, " >\n");
+ xmlDumpNotationDecl(buf, cur);
}
}
@@ -1537,7 +1705,7 @@
attrDecl = xmlGetDtdAttrDesc(doc->extSubset, elem->name,
attr->name);
- if ((attrDecl != NULL) && (attrDecl->type == XML_ATTRIBUTE_ID))
+ if ((attrDecl != NULL) && (attrDecl->atype == XML_ATTRIBUTE_ID))
return(1);
}
return(0);
@@ -1795,7 +1963,7 @@
attrDecl = xmlGetDtdAttrDesc(doc->extSubset, elem->name,
attr->name);
- if ((attrDecl != NULL) && (attrDecl->type == XML_ATTRIBUTE_IDREF))
+ if ((attrDecl != NULL) && (attrDecl->atype == XML_ATTRIBUTE_IDREF))
return(1);
}
return(0);
@@ -2022,7 +2190,7 @@
if ((elemDecl == NULL) && (doc->extSubset != NULL))
elemDecl = xmlGetDtdElementDesc(doc->extSubset, name);
if (elemDecl == NULL) return(-1);
- switch (elemDecl->type) {
+ switch (elemDecl->etype) {
case XML_ELEMENT_TYPE_ELEMENT:
return(0);
case XML_ELEMENT_TYPE_EMPTY:
@@ -2174,6 +2342,7 @@
if (value == NULL) return(0);
cur = value;
+ while (IS_BLANK(*cur)) cur++;
if (!IS_LETTER(*cur) && !IS_DIGIT(*cur) &&
(*cur != '.') && (*cur != '-') &&
(*cur != '_') && (*cur != ':') &&
@@ -2190,6 +2359,7 @@
while (IS_BLANK(*cur)) {
while (IS_BLANK(*cur)) cur++;
+ if (*cur == 0) return(1);
if (!IS_LETTER(*cur) && !IS_DIGIT(*cur) &&
(*cur != '.') && (*cur != '-') &&
@@ -2282,6 +2452,176 @@
}
/**
+ * xmlValidateAttributeValue2:
+ * @ctxt: the validation context
+ * @doc: the document
+ * @name: the attribute name (used for error reporting only)
+ * @type: the attribute type
+ * @value: the attribute value
+ *
+ * Validate that the given attribute value match a given type.
+ * This typically cannot be done before having finished parsing
+ * the subsets.
+ *
+ * [ VC: IDREF ]
+ * Values of type IDREF must match one of the declared IDs
+ * Values of type IDREFS must match a sequence of the declared IDs
+ * each Name must match the value of an ID attribute on some element
+ * in the XML document; i.e. IDREF values must match the value of
+ * some ID attribute
+ *
+ * [ VC: Entity Name ]
+ * Values of type ENTITY must match one declared entity
+ * Values of type ENTITIES must match a sequence of declared entities
+ *
+ * [ VC: Notation Attributes ]
+ * all notation names in the declaration must be declared.
+ *
+ * returns 1 if valid or 0 otherwise
+ */
+
+int
+xmlValidateAttributeValue2(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
+ const xmlChar *name, xmlAttributeType type, const xmlChar *value) {
+ int ret = 1;
+ switch (type) {
+ case XML_ATTRIBUTE_IDREFS:
+ case XML_ATTRIBUTE_IDREF:
+ case XML_ATTRIBUTE_ID:
+ case XML_ATTRIBUTE_NMTOKENS:
+ case XML_ATTRIBUTE_ENUMERATION:
+ case XML_ATTRIBUTE_NMTOKEN:
+ case XML_ATTRIBUTE_CDATA:
+ break;
+ case XML_ATTRIBUTE_ENTITY: {
+ xmlEntityPtr ent;
+
+ ent = xmlGetDocEntity(doc, value);
+ if (ent == NULL) {
+ VERROR(ctxt->userData,
+ "ENTITY attribute %s reference an unknown entity \"%s\"\n",
+ name, value);
+ ret = 0;
+ } else if (ent->etype != XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
+ VERROR(ctxt->userData,
+ "ENTITY attribute %s reference an entity \"%s\" of wrong type\n",
+ name, value);
+ ret = 0;
+ }
+ break;
+ }
+ case XML_ATTRIBUTE_ENTITIES: {
+ xmlChar *dup, *nam = NULL, *cur, save;
+ xmlEntityPtr ent;
+
+ dup = xmlStrdup(value);
+ if (dup == NULL)
+ return(0);
+ cur = dup;
+ while (*cur != 0) {
+ nam = cur;
+ while ((*cur != 0) && (!IS_BLANK(*cur))) cur++;
+ save = *cur;
+ *cur = 0;
+ ent = xmlGetDocEntity(doc, nam);
+ if (ent == NULL) {
+ VERROR(ctxt->userData,
+ "ENTITIES attribute %s reference an unknown entity \"%s\"\n",
+ name, nam);
+ ret = 0;
+ } else if (ent->etype != XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
+ VERROR(ctxt->userData,
+ "ENTITIES attribute %s reference an entity \"%s\" of wrong type\n",
+ name, nam);
+ ret = 0;
+ }
+ if (save == 0)
+ break;
+ *cur = save;
+ while (IS_BLANK(*cur)) cur++;
+ }
+ xmlFree(dup);
+ break;
+ }
+ case XML_ATTRIBUTE_NOTATION: {
+ xmlNotationPtr nota;
+
+ nota = xmlGetDtdNotationDesc(doc->intSubset, value);
+ if ((nota == NULL) && (doc->extSubset != NULL))
+ nota = xmlGetDtdNotationDesc(doc->extSubset, value);
+
+ if (nota == NULL) {
+ VERROR(ctxt->userData,
+ "NOTATION attribute %s reference an unknown notation \"%s\"\n",
+ name, value);
+ ret = 0;
+ }
+ break;
+ }
+ }
+ return(ret);
+}
+
+/**
+ * xmlValidNormalizeAttributeValue:
+ * @doc: the document
+ * @elem: the parent
+ * @name: the attribute name
+ * @value: the attribute value
+ *
+ * Does the validation related extra step of the normalization of attribute
+ * values:
+ *
+ * If the declared value is not CDATA, then the XML processor must further
+ * process the normalized attribute value by discarding any leading and
+ * trailing space (#x20) characters, and by replacing sequences of space
+ * (#x20) characters by single space (#x20) character.
+ *
+ * returns a new normalized string if normalization is needed, NULL otherwise
+ * the caller must free the returned value.
+ */
+
+xmlChar *
+xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem,
+ const xmlChar *name, const xmlChar *value) {
+ xmlChar *ret, *dst;
+ const xmlChar *src;
+ xmlAttributePtr attrDecl;
+
+ if (doc == NULL) return(NULL);
+ if (elem == NULL) return(NULL);
+ if (name == NULL) return(NULL);
+ if (value == NULL) return(NULL);
+
+ attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, name);
+ if ((attrDecl == NULL) && (doc->extSubset != NULL))
+ attrDecl = xmlGetDtdAttrDesc(doc->extSubset, elem->name, name);
+
+ if (attrDecl == NULL)
+ return(NULL);
+ if (attrDecl->atype == XML_ATTRIBUTE_CDATA)
+ return(NULL);
+
+ ret = xmlStrdup(value);
+ if (ret == NULL)
+ return(NULL);
+ src = value;
+ dst = ret;
+ while (*src == 0x20) src++;
+ while (*src != 0) {
+ if (*src == 0x20) {
+ while (*src == 0x20) src++;
+ if (*src != 0)
+ *dst++ = 0x20;
+ } else {
+ *dst++ = *src++;
+ }
+ }
+ *dst = 0;
+ return(ret);
+}
+
+/**
* xmlValidateAttributeDecl:
* @ctxt: the validation context
* @doc: a document instance
@@ -2310,7 +2650,7 @@
/* Attribute Default Legal */
/* Enumeration */
if (attr->defaultValue != NULL) {
- val = xmlValidateAttributeValue(attr->type, attr->defaultValue);
+ val = xmlValidateAttributeValue(attr->atype, attr->defaultValue);
if (val == 0) {
VERROR(ctxt->userData,
"Syntax of default value for attribute %s on %s is not valid\n",
@@ -2320,7 +2660,7 @@
}
/* ID Attribute Default */
- if ((attr->type == XML_ATTRIBUTE_ID)&&
+ if ((attr->atype == XML_ATTRIBUTE_ID)&&
(attr->def != XML_ATTRIBUTE_IMPLIED) &&
(attr->def != XML_ATTRIBUTE_REQUIRED)) {
VERROR(ctxt->userData,
@@ -2330,19 +2670,68 @@
}
/* One ID per Element Type */
- if ((attr->type == XML_ATTRIBUTE_ID) && (doc->extSubset != NULL)) {
- int nbId = 0;
+ if (attr->atype == XML_ATTRIBUTE_ID) {
+ int nbId;
/* the trick is taht we parse DtD as their own internal subset */
- xmlElementPtr elem = xmlGetDtdElementDesc(doc->extSubset,
+ xmlElementPtr elem = xmlGetDtdElementDesc(doc->intSubset,
attr->elem);
if (elem != NULL) {
nbId = xmlScanIDAttributeDecl(NULL, elem);
+ } else {
+ xmlAttributeTablePtr table;
+ int i;
+
+ /*
+ * The attribute may be declared in the internal subset and the
+ * element in the external subset.
+ */
+ nbId = 0;
+ table = doc->intSubset->attributes;
+ if (table != NULL) {
+ for (i = 0;i < table->nb_attributes;i++) {
+ if ((table->table[i]->atype == XML_ATTRIBUTE_ID) &&
+ (!xmlStrcmp(table->table[i]->elem, attr->elem))) {
+ nbId++;
+ }
+ }
+ }
}
- if (nbId >= 1)
+ if (nbId > 1) {
VERROR(ctxt->userData,
- "Element %s has ID attribute defined in the external subset : %s\n",
- attr->elem, attr->name);
+ "Element %s has %d ID attribute defined in the internal subset : %s\n",
+ attr->elem, nbId, attr->name);
+ } else if (doc->extSubset != NULL) {
+ int extId = 0;
+ elem = xmlGetDtdElementDesc(doc->extSubset, attr->elem);
+ if (elem != NULL) {
+ extId = xmlScanIDAttributeDecl(NULL, elem);
+ }
+ if (extId > 1) {
+ VERROR(ctxt->userData,
+ "Element %s has %d ID attribute defined in the external subset : %s\n",
+ attr->elem, extId, attr->name);
+ } else if (extId + nbId > 1) {
+ VERROR(ctxt->userData,
+"Element %s has ID attributes defined in the internal and external subset : %s\n",
+ attr->elem, attr->name);
+ }
+ }
+ }
+
+ /* Validity Constraint: Enumeration */
+ if ((attr->defaultValue != NULL) && (attr->tree != NULL)) {
+ xmlEnumerationPtr tree = attr->tree;
+ while (tree != NULL) {
+ if (!xmlStrcmp(tree->name, attr->defaultValue)) break;
+ tree = tree->next;
+ }
+ if (tree == NULL) {
+ VERROR(ctxt->userData,
+"Default value \"%s\" for attribute %s on %s is not among the enumerated set\n",
+ attr->defaultValue, attr->name, attr->elem);
+ ret = 0;
+ }
}
return(ret);
@@ -2375,7 +2764,7 @@
if (elem == NULL) return(1);
/* No Duplicate Types */
- if (elem->type == XML_ELEMENT_TYPE_MIXED) {
+ if (elem->etype == XML_ELEMENT_TYPE_MIXED) {
xmlElementContentPtr cur, next;
const xmlChar *name;
@@ -2441,7 +2830,7 @@
* @value: the attribute value (without entities processing)
*
* Try to validate a single attribute for an element
- * basically it * does the following checks as described by the
+ * basically it does the following checks as described by the
* XML-1.0 recommendation:
* - [ VC: Attribute Value Type ]
* - [ VC: Fixed Attribute Default ]
@@ -2481,7 +2870,9 @@
attr->name, elem->name);
return(0);
}
- val = xmlValidateAttributeValue(attrDecl->type, value);
+ attr->atype = attrDecl->atype;
+
+ val = xmlValidateAttributeValue(attrDecl->atype, value);
if (val == 0) {
VERROR(ctxt->userData,
"Syntax of value for attribute %s on %s is not valid\n",
@@ -2489,17 +2880,28 @@
ret = 0;
}
+ /* Validity constraint: Fixed Attribute Default */
+ if (attrDecl->def == XML_ATTRIBUTE_FIXED) {
+ if (xmlStrcmp(value, attrDecl->defaultValue)) {
+ VERROR(ctxt->userData,
+ "Value for attribute %s on %s is differnt from default \"%s\"\n",
+ attr->name, elem->name, attrDecl->defaultValue);
+ ret = 0;
+ }
+ }
+
/* Validity Constraint: ID uniqueness */
- if (attrDecl->type == XML_ATTRIBUTE_ID) {
+ if (attrDecl->atype == XML_ATTRIBUTE_ID) {
xmlAddID(ctxt, doc, value, attr);
}
- if (attrDecl->type == XML_ATTRIBUTE_IDREF) {
+ if ((attrDecl->atype == XML_ATTRIBUTE_IDREF) ||
+ (attrDecl->atype == XML_ATTRIBUTE_IDREFS)) {
xmlAddRef(ctxt, doc, value, attr);
}
/* Validity Constraint: Notation Attributes */
- if (attrDecl->type == XML_ATTRIBUTE_NOTATION) {
+ if (attrDecl->atype == XML_ATTRIBUTE_NOTATION) {
xmlEnumerationPtr tree = attrDecl->tree;
xmlNotationPtr nota;
@@ -2522,14 +2924,14 @@
}
if (tree == NULL) {
VERROR(ctxt->userData,
- "Value \"%s\" for attribute %s on %s is among the enumerated notations\n",
+"Value \"%s\" for attribute %s on %s is not among the enumerated notations\n",
value, attr->name, elem->name);
ret = 0;
}
}
/* Validity Constraint: Enumeration */
- if (attrDecl->type == XML_ATTRIBUTE_ENUMERATION) {
+ if (attrDecl->atype == XML_ATTRIBUTE_ENUMERATION) {
xmlEnumerationPtr tree = attrDecl->tree;
while (tree != NULL) {
if (!xmlStrcmp(tree->name, value)) break;
@@ -2552,14 +2954,10 @@
ret = 0;
}
- /********
- elemDecl = xmlGetDtdElementDesc(doc->intSubset, elem->name);
- if ((elemDecl == NULL) && (doc->extSubset != NULL))
- elemDecl = xmlGetDtdElementDesc(doc->extSubset, elem->name);
- if (elemDecl == NULL) {
- return(0);
- }
- ********/
+ /* Extra check for the attribute value */
+ ret &= xmlValidateAttributeValue2(ctxt, doc, attr->name,
+ attrDecl->atype, value);
+
return(ret);
}
@@ -2586,7 +2984,22 @@
int ret = 1;
if (cont == NULL) return(-1);
+ DEBUG_VALID_STATE(*child, cont)
while (*child != NULL) {
+ if ((*child)->type == XML_ENTITY_REF_NODE) {
+ /*
+ * If there is an entity declared an it's not empty
+ * Push the current node on the stack and process with the
+ * entity content.
+ */
+ if (((*child)->children != NULL) &&
+ ((*child)->children->children != NULL)) {
+ nodeVPush(ctxt, *child);
+ *child = (*child)->children->children;
+ } else
+ *child = (*child)->next;
+ continue;
+ }
if ((*child)->type == XML_PI_NODE) {
*child = (*child)->next;
continue;
@@ -2600,6 +3013,7 @@
}
break;
}
+ DEBUG_VALID_STATE(*child, cont)
switch (cont->type) {
case XML_ELEMENT_CONTENT_PCDATA:
if (*child == NULL) return(0);
@@ -2608,8 +3022,16 @@
case XML_ELEMENT_CONTENT_ELEMENT:
if (*child == NULL) return(0);
ret = (!xmlStrcmp((*child)->name, cont->name));
- if (ret == 1)
+ if (ret == 1) {
+ while ((*child)->next == NULL) {
+ if (((*child)->parent != NULL) &&
+ ((*child)->parent->type == XML_ENTITY_DECL)) {
+ *child = nodeVPop(ctxt);
+ } else
+ break;
+ }
*child = (*child)->next;
+ }
return(ret);
case XML_ELEMENT_CONTENT_OR:
cur = *child;
@@ -2666,7 +3088,23 @@
int ret = 1;
if (cont == NULL) return(-1);
+
+ DEBUG_VALID_STATE(*child, cont)
while (*child != NULL) {
+ if ((*child)->type == XML_ENTITY_REF_NODE) {
+ /*
+ * If there is an entity declared an it's not empty
+ * Push the current node on the stack and process with the
+ * entity content.
+ */
+ if (((*child)->children != NULL) &&
+ ((*child)->children->children != NULL)) {
+ nodeVPush(ctxt, *child);
+ *child = (*child)->children->children;
+ } else
+ *child = (*child)->next;
+ continue;
+ }
if ((*child)->type == XML_PI_NODE) {
*child = (*child)->next;
continue;
@@ -2680,6 +3118,7 @@
}
break;
}
+ DEBUG_VALID_STATE(*child, cont)
cur = *child;
ret = xmlValidateElementTypeExpr(ctxt, child, cont);
if (ret == -1) return(-1);
@@ -2690,7 +3129,14 @@
while ((*child != NULL) &&
(((*child)->type == XML_PI_NODE) ||
((*child)->type == XML_COMMENT_NODE))) {
- *child = (*child)->next;
+ while ((*child)->next == NULL) {
+ if (((*child)->parent != NULL) &&
+ ((*child)->parent->type == XML_ENTITY_REF_NODE)) {
+ *child = (*child)->parent;
+ } else
+ break;
+ }
+ *child = (*child)->next;
}
return(1);
}
@@ -2722,6 +3168,20 @@
break;
}
while (*child != NULL) {
+ if ((*child)->type == XML_ENTITY_REF_NODE) {
+ /*
+ * If there is an entity declared an it's not empty
+ * Push the current node on the stack and process with the
+ * entity content.
+ */
+ if (((*child)->children != NULL) &&
+ ((*child)->children->children != NULL)) {
+ nodeVPush(ctxt, *child);
+ *child = (*child)->children->children;
+ } else
+ *child = (*child)->next;
+ continue;
+ }
if ((*child)->type == XML_PI_NODE) {
*child = (*child)->next;
continue;
@@ -2753,7 +3213,7 @@
if (node == NULL) return;
if (glob) strcat(buf, "(");
- cur = node->childs;
+ cur = node->children;
while (cur != NULL) {
switch (cur->type) {
case XML_ELEMENT_NODE:
@@ -2780,7 +3240,11 @@
break;
case XML_ENTITY_NODE:
case XML_PI_NODE:
+ case XML_DTD_NODE:
case XML_COMMENT_NODE:
+ case XML_ELEMENT_DECL:
+ case XML_ATTRIBUTE_DECL:
+ case XML_ENTITY_DECL:
break;
}
cur = cur->next;
@@ -2828,7 +3292,7 @@
"Attribute element not expected here\n");
return(0);
case XML_TEXT_NODE:
- if (elem->childs != NULL) {
+ if (elem->children != NULL) {
VERROR(ctxt->userData, "Text element has childs !\n");
return(0);
}
@@ -2893,9 +3357,9 @@
}
/* Check taht the element content matches the definition */
- switch (elemDecl->type) {
+ switch (elemDecl->etype) {
case XML_ELEMENT_TYPE_EMPTY:
- if (elem->childs != NULL) {
+ if (elem->children != NULL) {
VERROR(ctxt->userData,
"Element %s was declared EMPTY this one has content\n",
elem->name);
@@ -2907,7 +3371,7 @@
break;
case XML_ELEMENT_TYPE_MIXED:
/* Hum, this start to get messy */
- child = elem->childs;
+ child = elem->children;
while (child != NULL) {
if (child->type == XML_ELEMENT_NODE) {
name = child->name;
@@ -2939,7 +3403,7 @@
}
break;
case XML_ELEMENT_TYPE_ELEMENT:
- child = elem->childs;
+ child = elem->children;
cont = elemDecl->content;
ret = xmlValidateElementTypeElement(ctxt, &child, cont);
if ((ret == 0) || (child != NULL)) {
@@ -3020,7 +3484,7 @@
}
}
found:
- attr = attr->next;
+ attr = attr->nexth;
}
return(ret);
}
@@ -3091,13 +3555,13 @@
ret &= xmlValidateOneElement(ctxt, doc, elem);
attr = elem->properties;
while(attr != NULL) {
- value = xmlNodeListGetString(doc, attr->val, 0);
+ value = xmlNodeListGetString(doc, attr->children, 0);
ret &= xmlValidateOneAttribute(ctxt, doc, elem, attr, value);
if (value != NULL)
xmlFree(value);
attr= attr->next;
}
- child = elem->childs;
+ child = elem->children;
while (child != NULL) {
ret &= xmlValidateElement(ctxt, doc, child);
child = child->next;
@@ -3132,17 +3596,50 @@
}
/*
- * Get the refs table
+ * Check all the NOTATION/NOTATIONS attributes
+ */
+ /*
+ * Check all the ENTITY/ENTITIES attributes definition for validity
+ */
+ /*
+ * Check all the IDREF/IDREFS attributes definition for validity
*/
table = doc->refs;
if (table != NULL) {
for (i = 0; i < table->nb_refs; i++) {
- id = xmlGetID(doc, table->table[i]->value);
- if (id == NULL) {
- VERROR(ctxt->userData,
- "IDREF attribute %s reference an unknown ID '%s'\n",
- table->table[i]->attr->name, table->table[i]->value);
- ret = 0;
+ if (table->table[i]->attr->atype == XML_ATTRIBUTE_IDREF) {
+ id = xmlGetID(doc, table->table[i]->value);
+ if (id == NULL) {
+ VERROR(ctxt->userData,
+ "IDREF attribute %s reference an unknown ID \"%s\"\n",
+ table->table[i]->attr->name, table->table[i]->value);
+ ret = 0;
+ }
+ } else if (table->table[i]->attr->atype == XML_ATTRIBUTE_IDREFS) {
+ xmlChar *dup, *name = NULL, *cur, save;
+
+ dup = xmlStrdup(table->table[i]->value);
+ if (dup == NULL)
+ return(0);
+ cur = dup;
+ while (*cur != 0) {
+ name = cur;
+ while ((*cur != 0) && (!IS_BLANK(*cur))) cur++;
+ save = *cur;
+ *cur = 0;
+ id = xmlGetID(doc, name);
+ if (id == NULL) {
+ VERROR(ctxt->userData,
+ "IDREFS attribute %s reference an unknown ID \"%s\"\n",
+ table->table[i]->attr->name, name);
+ ret = 0;
+ }
+ if (save == 0)
+ break;
+ *cur = save;
+ while (IS_BLANK(*cur)) cur++;
+ }
+ xmlFree(dup);
}
}
}
@@ -3185,6 +3682,102 @@
}
/**
+ * xmlValidateDtdFinal:
+ * @ctxt: the validation context
+ * @doc: a document instance
+ *
+ * Does the final step for the dtds validation once all the
+ * subsets have been parsed
+ *
+ * basically it does the following checks described by the XML Rec
+ * - check that ENTITY and ENTITIES type attributes default or
+ * possible values matches one of the defined entities.
+ * - check that NOTATION type attributes default or
+ * possible values matches one of the defined notations.
+ *
+ * returns 1 if valid or 0 otherwise
+ */
+
+int
+xmlValidateDtdFinal(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
+ int ret = 1, i;
+ xmlDtdPtr dtd;
+ xmlAttributeTablePtr table;
+ xmlAttributePtr cur;
+
+ if (doc == NULL) return(0);
+ if ((doc->intSubset == NULL) && (doc->extSubset == NULL))
+ return(0);
+ dtd = doc->intSubset;
+ if ((dtd != NULL) && (dtd->attributes != NULL)) {
+ table = dtd->attributes;
+
+ for (i = 0;i < table->nb_attributes;i++) {
+ cur = table->table[i];
+ switch (cur->atype) {
+ case XML_ATTRIBUTE_CDATA:
+ case XML_ATTRIBUTE_ID:
+ case XML_ATTRIBUTE_IDREF :
+ case XML_ATTRIBUTE_IDREFS:
+ case XML_ATTRIBUTE_NMTOKEN:
+ case XML_ATTRIBUTE_NMTOKENS:
+ case XML_ATTRIBUTE_ENUMERATION:
+ break;
+ case XML_ATTRIBUTE_ENTITY:
+ case XML_ATTRIBUTE_ENTITIES:
+ case XML_ATTRIBUTE_NOTATION:
+ if (cur->defaultValue != NULL) {
+ ret &= xmlValidateAttributeValue2(ctxt, doc, cur->name,
+ cur->atype, cur->defaultValue);
+ }
+ if (cur->tree != NULL) {
+ xmlEnumerationPtr tree = cur->tree;
+ while (tree != NULL) {
+ ret &= xmlValidateAttributeValue2(ctxt, doc,
+ cur->name, cur->atype, tree->name);
+ tree = tree->next;
+ }
+ }
+ }
+ }
+ }
+ dtd = doc->extSubset;
+ if ((dtd != NULL) && (dtd->attributes != NULL)) {
+ table = dtd->attributes;
+
+ for (i = 0;i < table->nb_attributes;i++) {
+ cur = table->table[i];
+ switch (cur->atype) {
+ case XML_ATTRIBUTE_CDATA:
+ case XML_ATTRIBUTE_ID:
+ case XML_ATTRIBUTE_IDREF :
+ case XML_ATTRIBUTE_IDREFS:
+ case XML_ATTRIBUTE_NMTOKEN:
+ case XML_ATTRIBUTE_NMTOKENS:
+ case XML_ATTRIBUTE_ENUMERATION:
+ break;
+ case XML_ATTRIBUTE_ENTITY:
+ case XML_ATTRIBUTE_ENTITIES:
+ case XML_ATTRIBUTE_NOTATION:
+ if (cur->defaultValue != NULL) {
+ ret &= xmlValidateAttributeValue2(ctxt, doc, cur->name,
+ cur->atype, cur->defaultValue);
+ }
+ if (cur->tree != NULL) {
+ xmlEnumerationPtr tree = cur->tree;
+ while (tree != NULL) {
+ ret &= xmlValidateAttributeValue2(ctxt, doc,
+ cur->name, cur->atype, tree->name);
+ tree = tree->next;
+ }
+ }
+ }
+ }
+ }
+ return(ret);
+}
+
+/**
* xmlValidateDocument:
* @ctxt: the validation context
* @doc: a document instance
@@ -3212,21 +3805,22 @@
if (doc->extSubset == NULL) {
if (doc->intSubset->SystemID != NULL) {
VERROR(ctxt->userData,
- "Could not load the external subset '%s'\n",
+ "Could not load the external subset \"%s\"\n",
doc->intSubset->SystemID);
} else {
VERROR(ctxt->userData,
- "Could not load the external subset '%s'\n",
+ "Could not load the external subset \"%s\"\n",
doc->intSubset->ExternalID);
}
return(0);
}
}
+ ret = xmlValidateDtdFinal(ctxt, doc);
if (!xmlValidateRoot(ctxt, doc)) return(0);
root = xmlDocGetRootElement(doc);
- ret = xmlValidateElement(ctxt, doc, root);
+ ret &= xmlValidateElement(ctxt, doc, root);
ret &= xmlValidateDocumentFinal(ctxt, doc);
return(ret);
}
@@ -3351,7 +3945,7 @@
*/
prev_next = prev ? prev->next : NULL;
next_prev = next ? next->prev : NULL;
- parent_childs = parent->childs;
+ parent_childs = parent->children;
parent_last = parent->last;
/*
@@ -3364,7 +3958,7 @@
test_node->next = next;
if (prev) prev->next = test_node;
- else parent->childs = test_node;
+ else parent->children = test_node;
if (next) next->prev = test_node;
else parent->last = test_node;
@@ -3393,7 +3987,7 @@
*/
if (prev) prev->next = prev_next;
if (next) next->prev = next_prev;
- parent->childs = parent_childs;
+ parent->children = parent_childs;
parent->last = parent_last;
return(nb_valid_elements);