mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-07-14 20:01:04 +03:00
- debugXML.c hash.c tree.h valid.c : some changes related to
the validation suport to improve speed with DocBook - result/VC/OneID2 result/VC/OneID3 : this slightly changes the way validation errors get reported Daniel
This commit is contained in:
@ -1,3 +1,10 @@
|
|||||||
|
Wed Apr 18 15:06:30 CEST 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
||||||
|
|
||||||
|
* debugXML.c hash.c tree.h valid.c : some changes related to
|
||||||
|
the validation suport to improve speed with DocBook
|
||||||
|
* result/VC/OneID2 result/VC/OneID3 : this slightly changes
|
||||||
|
the way validation errors get reported
|
||||||
|
|
||||||
Wed Apr 18 11:42:47 CEST 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
Wed Apr 18 11:42:47 CEST 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
||||||
|
|
||||||
* HTMLparser.c HTMLtree.c: applied part of the patches provided
|
* HTMLparser.c HTMLtree.c: applied part of the patches provided
|
||||||
|
@ -239,6 +239,9 @@ xmlDebugDumpElemDecl(FILE *output, xmlElementPtr elem, int depth) {
|
|||||||
} else
|
} else
|
||||||
fprintf(output, "PBM ELEMDECL noname!!!");
|
fprintf(output, "PBM ELEMDECL noname!!!");
|
||||||
switch (elem->etype) {
|
switch (elem->etype) {
|
||||||
|
case XML_ELEMENT_TYPE_UNDEFINED:
|
||||||
|
fprintf(output, ", UNDEFINED");
|
||||||
|
break;
|
||||||
case XML_ELEMENT_TYPE_EMPTY:
|
case XML_ELEMENT_TYPE_EMPTY:
|
||||||
fprintf(output, ", EMPTY");
|
fprintf(output, ", EMPTY");
|
||||||
break;
|
break;
|
||||||
|
196
hash.c
196
hash.c
@ -27,6 +27,11 @@
|
|||||||
#include <libxml/hash.h>
|
#include <libxml/hash.h>
|
||||||
#include <libxml/xmlmemory.h>
|
#include <libxml/xmlmemory.h>
|
||||||
#include <libxml/parser.h>
|
#include <libxml/parser.h>
|
||||||
|
#include <libxml/xmlerror.h>
|
||||||
|
|
||||||
|
#define MAX_HASH_LEN 8
|
||||||
|
|
||||||
|
/* #define DEBUG_GROW */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A single entry in the hash table
|
* A single entry in the hash table
|
||||||
@ -55,13 +60,29 @@ struct _xmlHashTable {
|
|||||||
* Calculate the hash key
|
* Calculate the hash key
|
||||||
*/
|
*/
|
||||||
static unsigned long
|
static unsigned long
|
||||||
xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *string) {
|
xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *name,
|
||||||
|
const xmlChar *name2, const xmlChar *name3) {
|
||||||
unsigned long value = 0L;
|
unsigned long value = 0L;
|
||||||
char ch;
|
char ch;
|
||||||
|
|
||||||
while ((ch = *string++) != 0) {
|
if (name != NULL) {
|
||||||
/* value *= 31; */
|
value += 30 * (*name);
|
||||||
value += (unsigned long)ch;
|
while ((ch = *name++) != 0) {
|
||||||
|
/* value *= 31; */
|
||||||
|
value += (unsigned long)ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (name2 != NULL) {
|
||||||
|
while ((ch = *name2++) != 0) {
|
||||||
|
/* value *= 31; */
|
||||||
|
value += (unsigned long)ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (name3 != NULL) {
|
||||||
|
while ((ch = *name3++) != 0) {
|
||||||
|
/* value *= 31; */
|
||||||
|
value += (unsigned long)ch;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return (value % table->size);
|
return (value % table->size);
|
||||||
}
|
}
|
||||||
@ -95,6 +116,77 @@ xmlHashCreate(int size) {
|
|||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlHashGrow:
|
||||||
|
* @table: the hash table
|
||||||
|
* @size: the new size of the hash table
|
||||||
|
*
|
||||||
|
* resize the hash table
|
||||||
|
*
|
||||||
|
* Returns 0 in case of success, -1 in case of failure
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xmlHashGrow(xmlHashTablePtr table, int size) {
|
||||||
|
unsigned long key;
|
||||||
|
int oldsize, i;
|
||||||
|
xmlHashEntryPtr iter, next;
|
||||||
|
struct _xmlHashEntry **oldtable;
|
||||||
|
#ifdef DEBUG_GROW
|
||||||
|
unsigned long nbElem = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (table == NULL)
|
||||||
|
return(-1);
|
||||||
|
if (size < 8)
|
||||||
|
return(-1);
|
||||||
|
if (size > 8 * 2048)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
oldsize = table->size;
|
||||||
|
oldtable = table->table;
|
||||||
|
if (oldtable == NULL)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
table->table = xmlMalloc(size * sizeof(xmlHashEntry));
|
||||||
|
if (table->table == NULL) {
|
||||||
|
table->table = oldtable;
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
memset(table->table, 0, size * sizeof(xmlHashEntry));
|
||||||
|
table->size = size;
|
||||||
|
|
||||||
|
for (i = 0; i < oldsize; i++) {
|
||||||
|
iter = oldtable[i];
|
||||||
|
while (iter) {
|
||||||
|
next = iter->next;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* put back the entry in the new table
|
||||||
|
*/
|
||||||
|
|
||||||
|
key = xmlHashComputeKey(table, iter->name, iter->name2,
|
||||||
|
iter->name3);
|
||||||
|
iter->next = table->table[key];
|
||||||
|
table->table[key] = iter;
|
||||||
|
|
||||||
|
#ifdef DEBUG_GROW
|
||||||
|
nbElem++;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
iter = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlFree(oldtable);
|
||||||
|
|
||||||
|
#ifdef DEBUG_GROW
|
||||||
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
|
"xmlHashGrow : from %d to %d, %d elems\n", oldsize, size, nbElem);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlHashFree:
|
* xmlHashFree:
|
||||||
* @table: the hash table
|
* @table: the hash table
|
||||||
@ -116,14 +208,14 @@ xmlHashFree(xmlHashTablePtr table, xmlHashDeallocator f) {
|
|||||||
iter = table->table[i];
|
iter = table->table[i];
|
||||||
while (iter) {
|
while (iter) {
|
||||||
next = iter->next;
|
next = iter->next;
|
||||||
|
if (f)
|
||||||
|
f(iter->payload, iter->name);
|
||||||
if (iter->name)
|
if (iter->name)
|
||||||
xmlFree(iter->name);
|
xmlFree(iter->name);
|
||||||
if (iter->name2)
|
if (iter->name2)
|
||||||
xmlFree(iter->name2);
|
xmlFree(iter->name2);
|
||||||
if (iter->name3)
|
if (iter->name3)
|
||||||
xmlFree(iter->name3);
|
xmlFree(iter->name3);
|
||||||
if (f)
|
|
||||||
f(iter->payload, iter->name);
|
|
||||||
iter->payload = NULL;
|
iter->payload = NULL;
|
||||||
xmlFree(iter);
|
xmlFree(iter);
|
||||||
iter = next;
|
iter = next;
|
||||||
@ -257,7 +349,7 @@ int
|
|||||||
xmlHashAddEntry3(xmlHashTablePtr table, const xmlChar *name,
|
xmlHashAddEntry3(xmlHashTablePtr table, const xmlChar *name,
|
||||||
const xmlChar *name2, const xmlChar *name3,
|
const xmlChar *name2, const xmlChar *name3,
|
||||||
void *userdata) {
|
void *userdata) {
|
||||||
unsigned long key;
|
unsigned long key, len = 0;
|
||||||
xmlHashEntryPtr entry;
|
xmlHashEntryPtr entry;
|
||||||
xmlHashEntryPtr insert;
|
xmlHashEntryPtr insert;
|
||||||
|
|
||||||
@ -267,7 +359,7 @@ xmlHashAddEntry3(xmlHashTablePtr table, const xmlChar *name,
|
|||||||
/*
|
/*
|
||||||
* Check for duplicate and insertion location.
|
* Check for duplicate and insertion location.
|
||||||
*/
|
*/
|
||||||
key = xmlHashComputeKey(table, name);
|
key = xmlHashComputeKey(table, name, name2, name3);
|
||||||
if (table->table[key] == NULL) {
|
if (table->table[key] == NULL) {
|
||||||
insert = NULL;
|
insert = NULL;
|
||||||
} else {
|
} else {
|
||||||
@ -277,6 +369,7 @@ xmlHashAddEntry3(xmlHashTablePtr table, const xmlChar *name,
|
|||||||
(xmlStrEqual(insert->name2, name2)) &&
|
(xmlStrEqual(insert->name2, name2)) &&
|
||||||
(xmlStrEqual(insert->name3, name3)))
|
(xmlStrEqual(insert->name3, name3)))
|
||||||
return(-1);
|
return(-1);
|
||||||
|
len++;
|
||||||
}
|
}
|
||||||
if ((xmlStrEqual(insert->name, name)) &&
|
if ((xmlStrEqual(insert->name, name)) &&
|
||||||
(xmlStrEqual(insert->name2, name2)) &&
|
(xmlStrEqual(insert->name2, name2)) &&
|
||||||
@ -300,6 +393,10 @@ xmlHashAddEntry3(xmlHashTablePtr table, const xmlChar *name,
|
|||||||
insert->next = entry;
|
insert->next = entry;
|
||||||
}
|
}
|
||||||
table->nbElems++;
|
table->nbElems++;
|
||||||
|
|
||||||
|
if (len > MAX_HASH_LEN)
|
||||||
|
xmlHashGrow(table, MAX_HASH_LEN * table->size);
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,7 +429,7 @@ xmlHashUpdateEntry3(xmlHashTablePtr table, const xmlChar *name,
|
|||||||
/*
|
/*
|
||||||
* Check for duplicate and insertion location.
|
* Check for duplicate and insertion location.
|
||||||
*/
|
*/
|
||||||
key = xmlHashComputeKey(table, name);
|
key = xmlHashComputeKey(table, name, name2, name3);
|
||||||
if (table->table[key] == NULL) {
|
if (table->table[key] == NULL) {
|
||||||
insert = NULL;
|
insert = NULL;
|
||||||
} else {
|
} else {
|
||||||
@ -397,7 +494,7 @@ xmlHashLookup3(xmlHashTablePtr table, const xmlChar *name,
|
|||||||
return(NULL);
|
return(NULL);
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
return(NULL);
|
return(NULL);
|
||||||
key = xmlHashComputeKey(table, name);
|
key = xmlHashComputeKey(table, name, name2, name3);
|
||||||
for (entry = table->table[key]; entry != NULL; entry = entry->next) {
|
for (entry = table->table[key]; entry != NULL; entry = entry->next) {
|
||||||
if ((xmlStrEqual(entry->name, name)) &&
|
if ((xmlStrEqual(entry->name, name)) &&
|
||||||
(xmlStrEqual(entry->name2, name2)) &&
|
(xmlStrEqual(entry->name2, name2)) &&
|
||||||
@ -544,8 +641,8 @@ xmlHashSize(xmlHashTablePtr table) {
|
|||||||
* Returns 0 if the removal succeeded and -1 in case of error or not found.
|
* Returns 0 if the removal succeeded and -1 in case of error or not found.
|
||||||
*/
|
*/
|
||||||
int xmlHashRemoveEntry(xmlHashTablePtr table, const xmlChar *name,
|
int xmlHashRemoveEntry(xmlHashTablePtr table, const xmlChar *name,
|
||||||
xmlHashDeallocator f) {
|
xmlHashDeallocator f) {
|
||||||
return(xmlHashRemoveEntry3(table, name, NULL, NULL, f));
|
return(xmlHashRemoveEntry3(table, name, NULL, NULL, f));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -561,8 +658,8 @@ int xmlHashRemoveEntry(xmlHashTablePtr table, const xmlChar *name,
|
|||||||
* Returns 0 if the removal succeeded and -1 in case of error or not found.
|
* Returns 0 if the removal succeeded and -1 in case of error or not found.
|
||||||
*/
|
*/
|
||||||
int xmlHashRemoveEntry2(xmlHashTablePtr table, const xmlChar *name,
|
int xmlHashRemoveEntry2(xmlHashTablePtr table, const xmlChar *name,
|
||||||
const xmlChar *name2, xmlHashDeallocator f) {
|
const xmlChar *name2, xmlHashDeallocator f) {
|
||||||
return(xmlHashRemoveEntry3(table, name, name2, NULL, f));
|
return(xmlHashRemoveEntry3(table, name, name2, NULL, f));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -579,43 +676,42 @@ int xmlHashRemoveEntry2(xmlHashTablePtr table, const xmlChar *name,
|
|||||||
* Returns 0 if the removal succeeded and -1 in case of error or not found.
|
* Returns 0 if the removal succeeded and -1 in case of error or not found.
|
||||||
*/
|
*/
|
||||||
int xmlHashRemoveEntry3(xmlHashTablePtr table, const xmlChar *name,
|
int xmlHashRemoveEntry3(xmlHashTablePtr table, const xmlChar *name,
|
||||||
const xmlChar *name2, const xmlChar *name3,
|
const xmlChar *name2, const xmlChar *name3, xmlHashDeallocator f) {
|
||||||
xmlHashDeallocator f) {
|
unsigned long key;
|
||||||
unsigned long key;
|
xmlHashEntryPtr entry;
|
||||||
xmlHashEntryPtr entry;
|
xmlHashEntryPtr prev = NULL;
|
||||||
xmlHashEntryPtr prev = NULL;
|
|
||||||
|
|
||||||
if (table == NULL || name == NULL)
|
if (table == NULL || name == NULL)
|
||||||
return(-1);
|
return(-1);
|
||||||
|
|
||||||
key = xmlHashComputeKey(table, name);
|
key = xmlHashComputeKey(table, name, name2, name3);
|
||||||
if (table->table[key] == NULL) {
|
if (table->table[key] == NULL) {
|
||||||
return(-1);
|
return(-1);
|
||||||
} else {
|
} else {
|
||||||
for (entry = table->table[key]; entry != NULL; entry = entry->next) {
|
for (entry = table->table[key]; entry != NULL; entry = entry->next) {
|
||||||
if (xmlStrEqual(entry->name, name) &&
|
if (xmlStrEqual(entry->name, name) &&
|
||||||
xmlStrEqual(entry->name2, name2) &&
|
xmlStrEqual(entry->name2, name2) &&
|
||||||
xmlStrEqual(entry->name3, name3)) {
|
xmlStrEqual(entry->name3, name3)) {
|
||||||
if(f)
|
if(f)
|
||||||
f(entry->payload, entry->name);
|
f(entry->payload, entry->name);
|
||||||
entry->payload = NULL;
|
entry->payload = NULL;
|
||||||
if(entry->name)
|
if(entry->name)
|
||||||
xmlFree(entry->name);
|
xmlFree(entry->name);
|
||||||
if(entry->name2)
|
if(entry->name2)
|
||||||
xmlFree(entry->name2);
|
xmlFree(entry->name2);
|
||||||
if(entry->name3)
|
if(entry->name3)
|
||||||
xmlFree(entry->name3);
|
xmlFree(entry->name3);
|
||||||
if(prev)
|
if(prev)
|
||||||
prev->next = entry->next;
|
prev->next = entry->next;
|
||||||
else
|
else
|
||||||
table->table[key] = entry->next;
|
table->table[key] = entry->next;
|
||||||
xmlFree(entry);
|
xmlFree(entry);
|
||||||
table->nbElems--;
|
table->nbElems--;
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
prev = entry;
|
prev = entry;
|
||||||
}
|
}
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,6 +172,7 @@ struct _xmlElementContent {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
XML_ELEMENT_TYPE_UNDEFINED = 0,
|
||||||
XML_ELEMENT_TYPE_EMPTY = 1,
|
XML_ELEMENT_TYPE_EMPTY = 1,
|
||||||
XML_ELEMENT_TYPE_ANY,
|
XML_ELEMENT_TYPE_ANY,
|
||||||
XML_ELEMENT_TYPE_MIXED,
|
XML_ELEMENT_TYPE_MIXED,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
./test/VC/OneID2:3: validity error: Element doc has too may ID attributes defined : id
|
||||||
|
<!ATTLIST doc id ID #IMPLIED>
|
||||||
|
^
|
||||||
./test/VC/OneID2:3: validity error: Element doc has 2 ID attribute defined in the internal subset : id
|
./test/VC/OneID2:3: validity error: Element doc has 2 ID attribute defined in the internal subset : id
|
||||||
<!ATTLIST doc id ID #IMPLIED>
|
<!ATTLIST doc id ID #IMPLIED>
|
||||||
^
|
^
|
||||||
./test/VC/OneID2:4: validity error: Element doc has too may ID attributes defined : val
|
|
||||||
<!ELEMENT doc (#PCDATA)>
|
|
||||||
^
|
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
test/VC/dtds/doc.dtd:2: validity error: Element doc has ID attributes defined in the internal and external subset : val
|
test/VC/dtds/doc.dtd:2: validity error: Element doc has too may ID attributes defined : val
|
||||||
|
<!ATTLIST doc val ID #IMPLIED>
|
||||||
|
^
|
||||||
|
test/VC/dtds/doc.dtd:2: validity error: Element doc has 2 ID attribute defined in the external subset : val
|
||||||
<!ATTLIST doc val ID #IMPLIED>
|
<!ATTLIST doc val ID #IMPLIED>
|
||||||
^
|
^
|
||||||
|
1
tree.h
1
tree.h
@ -172,6 +172,7 @@ struct _xmlElementContent {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
XML_ELEMENT_TYPE_UNDEFINED = 0,
|
||||||
XML_ELEMENT_TYPE_EMPTY = 1,
|
XML_ELEMENT_TYPE_EMPTY = 1,
|
||||||
XML_ELEMENT_TYPE_ANY,
|
XML_ELEMENT_TYPE_ANY,
|
||||||
XML_ELEMENT_TYPE_MIXED,
|
XML_ELEMENT_TYPE_MIXED,
|
||||||
|
189
valid.c
189
valid.c
@ -161,6 +161,8 @@ void xmlValidDebug(xmlNodePtr cur, xmlElementContentPtr cont) {
|
|||||||
(doc->extSubset == NULL)) return(0)
|
(doc->extSubset == NULL)) return(0)
|
||||||
|
|
||||||
xmlElementPtr xmlGetDtdElementDesc(xmlDtdPtr dtd, const xmlChar *name);
|
xmlElementPtr xmlGetDtdElementDesc(xmlDtdPtr dtd, const xmlChar *name);
|
||||||
|
static xmlElementPtr xmlGetDtdElementDesc2(xmlDtdPtr dtd, const xmlChar *name,
|
||||||
|
int create);
|
||||||
xmlAttributePtr xmlScanAttributeDecl(xmlDtdPtr dtd, const xmlChar *elem);
|
xmlAttributePtr xmlScanAttributeDecl(xmlDtdPtr dtd, const xmlChar *elem);
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
@ -507,6 +509,7 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name,
|
|||||||
xmlElementContentPtr content) {
|
xmlElementContentPtr content) {
|
||||||
xmlElementPtr ret;
|
xmlElementPtr ret;
|
||||||
xmlElementTablePtr table;
|
xmlElementTablePtr table;
|
||||||
|
xmlAttributePtr oldAttributes = NULL;
|
||||||
xmlChar *ns, *uqname;
|
xmlChar *ns, *uqname;
|
||||||
|
|
||||||
if (dtd == NULL) {
|
if (dtd == NULL) {
|
||||||
@ -575,38 +578,73 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name,
|
|||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
|
/*
|
||||||
if (ret == NULL) {
|
* lookup old attributes inserted on an undefined element in the
|
||||||
xmlGenericError(xmlGenericErrorContext,
|
* internal subset.
|
||||||
"xmlAddElementDecl: out of memory\n");
|
*/
|
||||||
return(NULL);
|
if ((dtd->doc != NULL) && (dtd->doc->intSubset != NULL)) {
|
||||||
|
ret = xmlHashLookup2(dtd->doc->intSubset->elements, name, ns);
|
||||||
|
if ((ret != NULL) && (ret->etype == XML_ELEMENT_TYPE_UNDEFINED)) {
|
||||||
|
oldAttributes = ret->attributes;
|
||||||
|
ret->attributes = NULL;
|
||||||
|
xmlHashRemoveEntry2(dtd->doc->intSubset->elements, name, ns, NULL);
|
||||||
|
xmlFreeElement(ret);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
memset(ret, 0, sizeof(xmlElement));
|
|
||||||
ret->type = XML_ELEMENT_DECL;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fill the structure.
|
* The element may already be present if one of its attribute
|
||||||
|
* was registered first
|
||||||
|
*/
|
||||||
|
ret = xmlHashLookup2(table, name, ns);
|
||||||
|
if (ret != NULL) {
|
||||||
|
if (ret->etype != XML_ELEMENT_TYPE_UNDEFINED) {
|
||||||
|
/*
|
||||||
|
* The element is already defined in this Dtd.
|
||||||
|
*/
|
||||||
|
VERROR(ctxt->userData, "Redefinition of element %s\n", name);
|
||||||
|
if (uqname != NULL)
|
||||||
|
xmlFree(uqname);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ret = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
|
||||||
|
if (ret == NULL) {
|
||||||
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
|
"xmlAddElementDecl: out of memory\n");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
memset(ret, 0, sizeof(xmlElement));
|
||||||
|
ret->type = XML_ELEMENT_DECL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fill the structure.
|
||||||
|
*/
|
||||||
|
ret->name = xmlStrdup(name);
|
||||||
|
ret->prefix = ns;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Validity Check:
|
||||||
|
* Insertion must not fail
|
||||||
|
*/
|
||||||
|
if (xmlHashAddEntry2(table, name, ns, ret)) {
|
||||||
|
/*
|
||||||
|
* The element is already defined in this Dtd.
|
||||||
|
*/
|
||||||
|
VERROR(ctxt->userData, "Redefinition of element %s\n", name);
|
||||||
|
xmlFreeElement(ret);
|
||||||
|
if (uqname != NULL)
|
||||||
|
xmlFree(uqname);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finish to fill the structure.
|
||||||
*/
|
*/
|
||||||
ret->etype = type;
|
ret->etype = type;
|
||||||
ret->name = xmlStrdup(name);
|
|
||||||
ret->prefix = ns;
|
|
||||||
ret->content = xmlCopyElementContent(content);
|
ret->content = xmlCopyElementContent(content);
|
||||||
ret->attributes = xmlScanAttributeDecl(dtd, name);
|
ret->attributes = oldAttributes;
|
||||||
|
|
||||||
/*
|
|
||||||
* Validity Check:
|
|
||||||
* Insertion must not fail
|
|
||||||
*/
|
|
||||||
if (xmlHashAddEntry2(table, name, ns, ret)) {
|
|
||||||
/*
|
|
||||||
* The element is already defined in this Dtd.
|
|
||||||
*/
|
|
||||||
VERROR(ctxt->userData, "Redefinition of element %s\n", name);
|
|
||||||
xmlFreeElement(ret);
|
|
||||||
if (uqname != NULL)
|
|
||||||
xmlFree(uqname);
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Link it to the Dtd
|
* Link it to the Dtd
|
||||||
@ -910,7 +948,7 @@ xmlScanIDAttributeDecl(xmlValidCtxtPtr ctxt, xmlElementPtr elem) {
|
|||||||
ret ++;
|
ret ++;
|
||||||
if (ret > 1)
|
if (ret > 1)
|
||||||
VERROR(ctxt->userData,
|
VERROR(ctxt->userData,
|
||||||
"Element %s has too may ID attributes defined : %s\n",
|
"Element %s has too many ID attributes defined : %s\n",
|
||||||
elem->name, cur->name);
|
elem->name, cur->name);
|
||||||
}
|
}
|
||||||
cur = cur->nexth;
|
cur = cur->nexth;
|
||||||
@ -1078,7 +1116,7 @@ xmlAddAttributeDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *elem,
|
|||||||
* Validity Check:
|
* Validity Check:
|
||||||
* Multiple ID per element
|
* Multiple ID per element
|
||||||
*/
|
*/
|
||||||
elemDef = xmlGetDtdElementDesc(dtd, elem);
|
elemDef = xmlGetDtdElementDesc2(dtd, elem, 1);
|
||||||
if (elemDef != NULL) {
|
if (elemDef != NULL) {
|
||||||
if ((type == XML_ATTRIBUTE_ID) &&
|
if ((type == XML_ATTRIBUTE_ID) &&
|
||||||
(xmlScanIDAttributeDecl(NULL, elemDef) != 0))
|
(xmlScanIDAttributeDecl(NULL, elemDef) != 0))
|
||||||
@ -1999,16 +2037,80 @@ xmlGetDtdElementDesc(xmlDtdPtr dtd, const xmlChar *name) {
|
|||||||
xmlChar *uqname = NULL, *prefix = NULL;
|
xmlChar *uqname = NULL, *prefix = NULL;
|
||||||
|
|
||||||
if (dtd == NULL) return(NULL);
|
if (dtd == NULL) return(NULL);
|
||||||
if (dtd->elements == NULL) return(NULL);
|
if (dtd->elements == NULL)
|
||||||
|
return(NULL);
|
||||||
table = (xmlElementTablePtr) dtd->elements;
|
table = (xmlElementTablePtr) dtd->elements;
|
||||||
|
|
||||||
uqname = xmlSplitQName2(name, &prefix);
|
uqname = xmlSplitQName2(name, &prefix);
|
||||||
if (uqname != NULL) {
|
if (uqname != NULL)
|
||||||
cur = xmlHashLookup2(table, uqname, prefix);
|
name = uqname;
|
||||||
if (prefix != NULL) xmlFree(prefix);
|
cur = xmlHashLookup2(table, name, prefix);
|
||||||
if (uqname != NULL) xmlFree(uqname);
|
if (prefix != NULL) xmlFree(prefix);
|
||||||
} else
|
if (uqname != NULL) xmlFree(uqname);
|
||||||
cur = xmlHashLookup2(table, name, NULL);
|
return(cur);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* xmlGetDtdElementDesc2:
|
||||||
|
* @dtd: a pointer to the DtD to search
|
||||||
|
* @name: the element name
|
||||||
|
* @create: create an empty description if not found
|
||||||
|
*
|
||||||
|
* Search the Dtd for the description of this element
|
||||||
|
*
|
||||||
|
* returns the xmlElementPtr if found or NULL
|
||||||
|
*/
|
||||||
|
|
||||||
|
xmlElementPtr
|
||||||
|
xmlGetDtdElementDesc2(xmlDtdPtr dtd, const xmlChar *name, int create) {
|
||||||
|
xmlElementTablePtr table;
|
||||||
|
xmlElementPtr cur;
|
||||||
|
xmlChar *uqname = NULL, *prefix = NULL;
|
||||||
|
|
||||||
|
if (dtd == NULL) return(NULL);
|
||||||
|
if (dtd->elements == NULL) {
|
||||||
|
if (!create)
|
||||||
|
return(NULL);
|
||||||
|
/*
|
||||||
|
* Create the Element table if needed.
|
||||||
|
*/
|
||||||
|
table = (xmlElementTablePtr) dtd->elements;
|
||||||
|
if (table == NULL) {
|
||||||
|
table = xmlCreateElementTable();
|
||||||
|
dtd->elements = (void *) table;
|
||||||
|
}
|
||||||
|
if (table == NULL) {
|
||||||
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
|
"xmlGetDtdElementDesc: Table creation failed!\n");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
table = (xmlElementTablePtr) dtd->elements;
|
||||||
|
|
||||||
|
uqname = xmlSplitQName2(name, &prefix);
|
||||||
|
if (uqname != NULL)
|
||||||
|
name = uqname;
|
||||||
|
cur = xmlHashLookup2(table, name, prefix);
|
||||||
|
if ((cur == NULL) && (create)) {
|
||||||
|
cur = (xmlElementPtr) xmlMalloc(sizeof(xmlElement));
|
||||||
|
if (cur == NULL) {
|
||||||
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
|
"xmlGetDtdElementDesc: out of memory\n");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
memset(cur, 0, sizeof(xmlElement));
|
||||||
|
cur->type = XML_ELEMENT_DECL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fill the structure.
|
||||||
|
*/
|
||||||
|
cur->name = xmlStrdup(name);
|
||||||
|
cur->prefix = xmlStrdup(prefix);
|
||||||
|
cur->etype = XML_ELEMENT_TYPE_UNDEFINED;
|
||||||
|
|
||||||
|
xmlHashAddEntry2(table, name, prefix, cur);
|
||||||
|
}
|
||||||
|
if (prefix != NULL) xmlFree(prefix);
|
||||||
|
if (uqname != NULL) xmlFree(uqname);
|
||||||
return(cur);
|
return(cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2169,6 +2271,8 @@ xmlIsMixedElement(xmlDocPtr doc, const xmlChar *name) {
|
|||||||
elemDecl = xmlGetDtdElementDesc(doc->extSubset, name);
|
elemDecl = xmlGetDtdElementDesc(doc->extSubset, name);
|
||||||
if (elemDecl == NULL) return(-1);
|
if (elemDecl == NULL) return(-1);
|
||||||
switch (elemDecl->etype) {
|
switch (elemDecl->etype) {
|
||||||
|
case XML_ELEMENT_TYPE_UNDEFINED:
|
||||||
|
return(-1);
|
||||||
case XML_ELEMENT_TYPE_ELEMENT:
|
case XML_ELEMENT_TYPE_ELEMENT:
|
||||||
return(0);
|
return(0);
|
||||||
case XML_ELEMENT_TYPE_EMPTY:
|
case XML_ELEMENT_TYPE_EMPTY:
|
||||||
@ -2788,22 +2892,25 @@ xmlValidateElementDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
|
|||||||
|
|
||||||
/* VC: Unique Element Type Declaration */
|
/* VC: Unique Element Type Declaration */
|
||||||
tst = xmlGetDtdElementDesc(doc->intSubset, elem->name);
|
tst = xmlGetDtdElementDesc(doc->intSubset, elem->name);
|
||||||
if ((tst != NULL ) && (tst != elem)) {
|
if ((tst != NULL ) && (tst != elem) &&
|
||||||
|
(tst->etype != XML_ELEMENT_TYPE_UNDEFINED)) {
|
||||||
VERROR(ctxt->userData, "Redefinition of element %s\n",
|
VERROR(ctxt->userData, "Redefinition of element %s\n",
|
||||||
elem->name);
|
elem->name);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
tst = xmlGetDtdElementDesc(doc->extSubset, elem->name);
|
tst = xmlGetDtdElementDesc(doc->extSubset, elem->name);
|
||||||
if ((tst != NULL ) && (tst != elem)) {
|
if ((tst != NULL ) && (tst != elem) &&
|
||||||
|
(tst->etype != XML_ELEMENT_TYPE_UNDEFINED)) {
|
||||||
VERROR(ctxt->userData, "Redefinition of element %s\n",
|
VERROR(ctxt->userData, "Redefinition of element %s\n",
|
||||||
elem->name);
|
elem->name);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* One ID per Element Type */
|
/* One ID per Element Type
|
||||||
|
* already done when registering the attribute
|
||||||
if (xmlScanIDAttributeDecl(ctxt, elem) > 1) {
|
if (xmlScanIDAttributeDecl(ctxt, elem) > 1) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
} */
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3426,6 +3533,10 @@ xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
|
|||||||
|
|
||||||
/* Check taht the element content matches the definition */
|
/* Check taht the element content matches the definition */
|
||||||
switch (elemDecl->etype) {
|
switch (elemDecl->etype) {
|
||||||
|
case XML_ELEMENT_TYPE_UNDEFINED:
|
||||||
|
VERROR(ctxt->userData, "No declaration for element %s\n",
|
||||||
|
elem->name);
|
||||||
|
return(0);
|
||||||
case XML_ELEMENT_TYPE_EMPTY:
|
case XML_ELEMENT_TYPE_EMPTY:
|
||||||
if (elem->children != NULL) {
|
if (elem->children != NULL) {
|
||||||
VERROR(ctxt->userData,
|
VERROR(ctxt->userData,
|
||||||
|
Reference in New Issue
Block a user