Bug fixes, improvement on ID/IDREF support, 1.6.2, no memleaks, Daniel
diff --git a/ChangeLog b/ChangeLog
index a60e0a7..e939c0c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+Wed Sep 8 22:46:14 CEST 1999 Daniel Veillard <Daniel.Veillard@w3.org>
+
+ * HTMLparser.c : cleanup
+ * SAX.c valid.c valid.h: added ID/IDREF checking
+ * tree.c tree.h: extended doc structure for refs
+ * configure.in: 1.6.2
+ * parser.c: patched bug in SAX user arg call
+ * parserInternals.h: patched missing close in C++ wrapping
+ * testXPath.c xpath.c xpath.h: prepared for extensibility,
+ especially upcoming XPointer implementation.
+ * doc/xml.html: augmented, typo
+
Sat Sep 4 22:48:05 CEST 1999 Timur Bakeyev <mc@bat.ru>
* doc/Makefile.am: replaced "install -d " with "mkinstalldirs" -
diff --git a/HACKING b/HACKING
index 6b702fa..8f791bc 100644
--- a/HACKING
+++ b/HACKING
@@ -15,7 +15,7 @@
The reasons I'm asking for an ask before commit policy is that I'm
using a separate CVS base for unstable developments and if you commit
a patch I didn't get, I may loose your change by mistake (it happened
-already once) and seriously complicatye my job of merging both bases.
+already once) and seriously complicates my job of merging both bases.
(The second base is at http://dev.w3.org/ under the XML module).
thanks in advance for following the rule,
diff --git a/HTMLparser.c b/HTMLparser.c
index adfa2d9..a559d9b 100644
--- a/HTMLparser.c
+++ b/HTMLparser.c
@@ -1133,6 +1133,8 @@
cur->encoding = NULL;
cur->standalone = 1;
cur->compression = 0;
+ cur->ids = NULL;
+ cur->refs = NULL;
#ifndef XML_WITHOUT_CORBA
cur->_private = NULL;
cur->vepv = NULL;
diff --git a/SAX.c b/SAX.c
index 57443ed..d0c08fe 100644
--- a/SAX.c
+++ b/SAX.c
@@ -492,10 +492,13 @@
void
endDocument(void *ctx)
{
- /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
+ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
#ifdef DEBUG_SAX
fprintf(stderr, "SAX.endDocument()\n");
#endif
+ if (ctxt->validate && ctxt->wellFormed &&
+ ctxt->myDoc && ctxt->myDoc->intSubset)
+ ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
}
/**
@@ -572,6 +575,8 @@
*/
if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
+ else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
+ xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
}
if (name != NULL)
diff --git a/configure.in b/configure.in
index 7d33d2b..49d5708 100644
--- a/configure.in
+++ b/configure.in
@@ -5,7 +5,7 @@
LIBXML_MAJOR_VERSION=1
LIBXML_MINOR_VERSION=6
-LIBXML_MICRO_VERSION=1
+LIBXML_MICRO_VERSION=2
LIBXML_VERSION=$LIBXML_MAJOR_VERSION.$LIBXML_MINOR_VERSION.$LIBXML_MICRO_VERSION
LIBXML_VERSION_INFO=`expr $LIBXML_MAJOR_VERSION + $LIBXML_MINOR_VERSION`:$LIBXML_MICRO_VERSION:$LIBXML_MINOR_VERSION
diff --git a/doc/xml.html b/doc/xml.html
index 49e0899..a5afae1 100644
--- a/doc/xml.html
+++ b/doc/xml.html
@@ -529,7 +529,7 @@
Model</em> this is an API for accessing XML or HTML structured documents.
Native support for DOM in Gnome is on the way (module gnome-dom), and it will
be based on gnome-xml. This will be a far cleaner interface to manipulate XML
-files within Gnome since it won't expose the internal structure. DOM defiles a
+files within Gnome since it won't expose the internal structure. DOM defines a
set of IDL (or Java) interfaces allowing to traverse and manipulate a
document. The DOM library will allow accessing and modifying "live" documents
presents on other programs like this:</p>
@@ -747,6 +747,6 @@
<p><a href="mailto:Daniel.Veillard@w3.org">Daniel Veillard</a></p>
-<p>$Id$</p>
+<p>$Id: xml.html,v 1.7 1999/09/04 18:27:23 veillard Exp $</p>
</body>
</html>
diff --git a/include/libxml/parserInternals.h b/include/libxml/parserInternals.h
index 13ea136..cb28943 100644
--- a/include/libxml/parserInternals.h
+++ b/include/libxml/parserInternals.h
@@ -637,4 +637,7 @@
xmlParserInputPtr value);
xmlParserInputPtr inputPop (xmlParserCtxtPtr ctxt);
+#ifdef __cplusplus
+}
+#endif
#endif /* __XML_PARSER_INTERNALS_H__ */
diff --git a/include/libxml/tree.h b/include/libxml/tree.h
index 6d22ac1..bf8a77e 100644
--- a/include/libxml/tree.h
+++ b/include/libxml/tree.h
@@ -211,6 +211,17 @@
typedef xmlID *xmlIDPtr;
/*
+ * An XML IDREF instance.
+ */
+
+typedef struct xmlRef {
+ struct xmlRef *next; /* next Ref */
+ const CHAR *value; /* The Ref name */
+ xmlAttrPtr attr; /* The attribut holding it */
+} xmlRef;
+typedef xmlRef *xmlRefPtr;
+
+/*
* A node in an XML tree.
*/
typedef struct xmlNode {
@@ -253,6 +264,7 @@
struct xmlNs *oldNs; /* Global namespace, the old way */
struct xmlNode *root; /* the document tree */
void *ids; /* Hash table for ID attributes if any */
+ void *refs; /* Hash table for IDREFs attributes if any */
} _xmlDoc;
typedef _xmlDoc xmlDoc;
typedef xmlDoc *xmlDocPtr;
@@ -441,6 +453,12 @@
const CHAR *lang);
/*
+ * Removing content.
+ */
+int xmlRemoveProp (xmlAttrPtr attr); /* TODO */
+int xmlRemoveNode (xmlNodePtr node); /* TODO */
+
+/*
* Internal, don't use
*/
void xmlBufferWriteCHAR (xmlBufferPtr buf,
diff --git a/include/libxml/valid.h b/include/libxml/valid.h
index 37b4f99..22a2c27 100644
--- a/include/libxml/valid.h
+++ b/include/libxml/valid.h
@@ -88,6 +88,20 @@
} xmlIDTable;
typedef xmlIDTable *xmlIDTablePtr;
+/*
+ * ALl Refs attributes are stored in a table
+ * there is one table per document
+ */
+
+#define XML_MIN_REF_TABLE 32
+
+typedef struct xmlRefTable {
+ int nb_refs; /* number of refs stored */
+ int max_refs; /* maximum number of refs */
+ xmlRefPtr *table; /* the table of refs */
+} xmlRefTable;
+typedef xmlRefTable *xmlRefTablePtr;
+
/* Notation */
xmlNotationPtr xmlAddNotationDecl (xmlValidCtxtPtr ctxt,
xmlDtdPtr dtd,
@@ -148,6 +162,17 @@
xmlNodePtr elem,
xmlAttrPtr attr);
+/* IDREFs */
+xmlRefPtr xmlAddRef (xmlValidCtxtPtr ctxt,
+ xmlDocPtr doc,
+ const CHAR *value,
+ xmlAttrPtr attr);
+xmlRefTablePtr xmlCopyRefTable (xmlRefTablePtr table);
+void xmlFreeRefTable (xmlRefTablePtr table);
+int xmlIsRef (xmlDocPtr doc,
+ xmlNodePtr elem,
+ xmlAttrPtr attr);
+
/**
* The public function calls related to validity checking
*/
@@ -181,6 +206,8 @@
xmlNodePtr elem,
xmlAttrPtr attr,
const CHAR *value);
+int xmlValidateDocumentFinal(xmlValidCtxtPtr ctxt,
+ xmlDocPtr doc);
int xmlValidateNotationUse (xmlValidCtxtPtr ctxt,
xmlDocPtr doc,
const CHAR *notationName);
diff --git a/include/libxml/xpath.h b/include/libxml/xpath.h
index 6408503..d46c063 100644
--- a/include/libxml/xpath.h
+++ b/include/libxml/xpath.h
@@ -14,6 +14,8 @@
#include "tree.h"
+typedef struct xmlXPathParserContext *xmlXPathParserContextPtr;
+
/*
* A node-set (an unordered collection of nodes without duplicates)
*/
@@ -37,6 +39,7 @@
#define XPATH_BOOLEAN 2
#define XPATH_NUMBER 3
#define XPATH_STRING 4
+#define XPATH_USERS 5
typedef struct xmlXPathObject {
int type;
@@ -44,8 +47,66 @@
int boolval;
double floatval;
CHAR *stringval;
+ void *user;
} xmlXPathObject, *xmlXPathObjectPtr;
+/*
+ * A conversion function is associated to a type and used to cast
+ * the new type to primitive values.
+ */
+typedef int (*xmlXPathConvertFunc) (xmlXPathObjectPtr obj, int type);
+
+/*
+ * Extra type: a name and a conversion function.
+ */
+
+typedef struct xmlXPathType {
+ const CHAR *name; /* the type name */
+ xmlXPathConvertFunc func; /* the conversion function */
+} xmlXPathType, *xmlXPathTypePtr;
+
+/*
+ * Extra variable: a name and a value.
+ */
+
+typedef struct xmlXPathVariable {
+ const CHAR *name; /* the variable name */
+ xmlXPathObjectPtr value; /* the value */
+} xmlXPathVariable, *xmlXPathVariablePtr;
+
+/*
+ * an evaluation function, the parameters are on the context stack
+ */
+
+typedef void (*xmlXPathEvalFunc)(xmlXPathParserContextPtr ctxt, int nargs);
+
+/*
+ * Extra function: a name and a evaluation function.
+ */
+
+typedef struct xmlXPathFunct {
+ const CHAR *name; /* the function name */
+ xmlXPathEvalFunc func; /* the evaluation function */
+} xmlXPathFunc, *xmlXPathFuncPtr;
+
+/*
+ * An axis traversal function. To traverse an axis, the engine calls
+ * the first time with cur == NULL and repeat until the function returns
+ * NULL indicating the end of the axis traversal.
+ */
+
+typedef xmlXPathObjectPtr (*xmlXPathAxisFunc) (xmlXPathParserContextPtr ctxt,
+ xmlXPathObjectPtr cur);
+
+/*
+ * Extra axis: a name and an axis function.
+ */
+
+typedef struct xmlXPathAxis {
+ const CHAR *name; /* the axis name */
+ xmlXPathAxisFunc func; /* the search function */
+} xmlXPathAxis, *xmlXPathAxisPtr;
+
/*
* Expression evaluation occurs with respect to a context.
* he context consists of:
@@ -60,10 +121,27 @@
xmlDocPtr doc; /* The current document */
xmlNodePtr node; /* The current node */
xmlNodeSetPtr nodelist; /* The current node list */
- void *variables; /* TODO !!!! */
- void *functions; /* TODO !!!! */
+
+ int nb_variables; /* number of defined variables */
+ int max_variables; /* max number of variables */
+ xmlXPathVariablePtr *variables; /* Array of defined variables */
+
+ int nb_types; /* number of defined types */
+ int max_types; /* max number of types */
+ xmlXPathTypePtr *types; /* Array of defined types */
+
+ int nb_funcs; /* number of defined funcs */
+ int max_funcs; /* max number of funcs */
+ xmlXPathFuncPtr *funcs; /* Array of defined funcs */
+
+ int nb_axis; /* number of defined axis */
+ int max_axis; /* max number of axis */
+ xmlXPathAxisPtr *axis; /* Array of defined axis */
+
+ /* Namespace traversal should be implemented with user */
xmlNsPtr *namespaces; /* The namespaces lookup */
int nsNr; /* the current Namespace index */
+ void *user; /* user defined extra info */
} xmlXPathContext, *xmlXPathContextPtr;
/*
@@ -81,7 +159,7 @@
int valueNr; /* number of values stacked */
int valueMax; /* max number of values stacked */
xmlXPathObjectPtr *valueTab; /* stack of values */
-} xmlXPathParserContext, *xmlXPathParserContextPtr;
+} xmlXPathParserContext;
/*
* An XPath function
@@ -97,9 +175,26 @@
* *
************************************************************************/
-xmlXPathContextPtr xmlXPathNewContext (xmlDocPtr doc,
- void *variables,
- void *functions);
+/**
+ * Registering extensions to the expression language
+ */
+/* TODO */ int xmlXPathRegisterType (xmlXPathContextPtr ctxt,
+ const CHAR *name,
+ xmlXPathConvertFunc f);
+/* TODO */ int xmlXPathRegisterAxis (xmlXPathContextPtr ctxt,
+ const CHAR *name,
+ xmlXPathAxisFunc f);
+/* TODO */ int xmlXPathRegisterFunc (xmlXPathContextPtr ctxt,
+ const CHAR *name,
+ xmlXPathFunction f);
+/* TODO */ int xmlXPathRegisterVariable (xmlXPathContextPtr ctxt,
+ const CHAR *name,
+ xmlXPathObject value);
+
+/**
+ * Evaluation functions.
+ */
+xmlXPathContextPtr xmlXPathNewContext (xmlDocPtr doc);
void xmlXPathFreeContext (xmlXPathContextPtr ctxt);
xmlXPathObjectPtr xmlXPathEval (const CHAR *str,
xmlXPathContextPtr ctxt);
diff --git a/parser.c b/parser.c
index 0f3e7cf..1b353fb 100644
--- a/parser.c
+++ b/parser.c
@@ -3122,11 +3122,11 @@
if (isParameter) {
if ((ctxt->sax != NULL) &&
(ctxt->sax->getParameterEntity != NULL))
- cur = ctxt->sax->getParameterEntity(ctxt, name);
+ cur = ctxt->sax->getParameterEntity(ctxt->userData, name);
} else {
if ((ctxt->sax != NULL) &&
(ctxt->sax->getEntity != NULL))
- cur = ctxt->sax->getEntity(ctxt, name);
+ cur = ctxt->sax->getEntity(ctxt->userData, name);
}
if (cur != NULL) {
if (cur->orig != NULL)
diff --git a/parserInternals.h b/parserInternals.h
index 13ea136..cb28943 100644
--- a/parserInternals.h
+++ b/parserInternals.h
@@ -637,4 +637,7 @@
xmlParserInputPtr value);
xmlParserInputPtr inputPop (xmlParserCtxtPtr ctxt);
+#ifdef __cplusplus
+}
+#endif
#endif /* __XML_PARSER_INTERNALS_H__ */
diff --git a/testXPath.c b/testXPath.c
index 178f23e..5045396 100644
--- a/testXPath.c
+++ b/testXPath.c
@@ -125,7 +125,7 @@
xmlXPathObjectPtr res;
xmlXPathContextPtr ctxt;
- ctxt = xmlXPathNewContext(document, NULL, NULL);
+ ctxt = xmlXPathNewContext(document);
if (expr)
res = xmlXPathEvalExpression(BAD_CAST str, ctxt);
else
diff --git a/tree.c b/tree.c
index 9e622ff..006defe 100644
--- a/tree.c
+++ b/tree.c
@@ -395,6 +395,7 @@
cur->standalone = -1;
cur->compression = xmlCompressMode;
cur->ids = NULL;
+ cur->refs = NULL;
#ifndef XML_WITHOUT_CORBA
cur->_private = NULL;
cur->vepv = NULL;
@@ -425,6 +426,7 @@
if (cur->extSubset != NULL) xmlFreeDtd(cur->extSubset);
if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
+ if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
memset(cur, -1, sizeof(xmlDoc));
xmlFree(cur);
}
diff --git a/tree.h b/tree.h
index 6d22ac1..bf8a77e 100644
--- a/tree.h
+++ b/tree.h
@@ -211,6 +211,17 @@
typedef xmlID *xmlIDPtr;
/*
+ * An XML IDREF instance.
+ */
+
+typedef struct xmlRef {
+ struct xmlRef *next; /* next Ref */
+ const CHAR *value; /* The Ref name */
+ xmlAttrPtr attr; /* The attribut holding it */
+} xmlRef;
+typedef xmlRef *xmlRefPtr;
+
+/*
* A node in an XML tree.
*/
typedef struct xmlNode {
@@ -253,6 +264,7 @@
struct xmlNs *oldNs; /* Global namespace, the old way */
struct xmlNode *root; /* the document tree */
void *ids; /* Hash table for ID attributes if any */
+ void *refs; /* Hash table for IDREFs attributes if any */
} _xmlDoc;
typedef _xmlDoc xmlDoc;
typedef xmlDoc *xmlDocPtr;
@@ -441,6 +453,12 @@
const CHAR *lang);
/*
+ * Removing content.
+ */
+int xmlRemoveProp (xmlAttrPtr attr); /* TODO */
+int xmlRemoveNode (xmlNodePtr node); /* TODO */
+
+/*
* Internal, don't use
*/
void xmlBufferWriteCHAR (xmlBufferPtr buf,
diff --git a/valid.c b/valid.c
index 3a107db..a6466ff 100644
--- a/valid.c
+++ b/valid.c
@@ -1316,7 +1316,7 @@
/************************************************************************
* *
- * NOTATIONs *
+ * IDs *
* *
************************************************************************/
/**
@@ -1551,6 +1551,228 @@
/************************************************************************
* *
+ * Refs *
+ * *
+ ************************************************************************/
+/**
+ * xmlCreateRefTable:
+ *
+ * create and initialize an empty ref hash table.
+ *
+ * Returns the xmlRefTablePtr just created or NULL in case
+ * of error.
+ */
+xmlRefTablePtr
+xmlCreateRefTable(void) {
+ xmlRefTablePtr ret;
+
+ ret = (xmlRefTablePtr)
+ xmlMalloc(sizeof(xmlRefTable));
+ if (ret == NULL) {
+ fprintf(stderr, "xmlCreateRefTable : xmlMalloc(%ld) failed\n",
+ (long)sizeof(xmlRefTable));
+ return(NULL);
+ }
+ ret->max_refs = XML_MIN_NOTATION_TABLE;
+ ret->nb_refs = 0;
+ ret->table = (xmlRefPtr *)
+ xmlMalloc(ret->max_refs * sizeof(xmlRefPtr));
+ if (ret == NULL) {
+ fprintf(stderr, "xmlCreateRefTable : xmlMalloc(%ld) failed\n",
+ ret->max_refs * (long)sizeof(xmlRef));
+ xmlFree(ret);
+ return(NULL);
+ }
+ return(ret);
+}
+
+
+/**
+ * xmlAddRef:
+ * @ctxt: the validation context
+ * @doc: pointer to the document
+ * @value: the value name
+ * @attr: the attribute holding the Ref
+ *
+ * Register a new ref declaration
+ *
+ * Returns NULL if not, othervise the new xmlRefPtr
+ */
+xmlRefPtr
+xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const CHAR *value,
+ xmlAttrPtr attr) {
+ xmlRefPtr ret;
+ xmlRefTablePtr table;
+
+ if (doc == NULL) {
+ fprintf(stderr, "xmlAddRefDecl: doc == NULL\n");
+ return(NULL);
+ }
+ if (value == NULL) {
+ fprintf(stderr, "xmlAddRefDecl: value == NULL\n");
+ return(NULL);
+ }
+ if (attr == NULL) {
+ fprintf(stderr, "xmlAddRefDecl: attr == NULL\n");
+ return(NULL);
+ }
+
+ /*
+ * Create the Ref table if needed.
+ */
+ table = doc->refs;
+ if (table == NULL)
+ table = doc->refs = xmlCreateRefTable();
+ if (table == NULL) {
+ fprintf(stderr, "xmlAddRef: Table creation failed!\n");
+ return(NULL);
+ }
+
+ /*
+ * Grow the table, if needed.
+ */
+ if (table->nb_refs >= table->max_refs) {
+ /*
+ * need more refs.
+ */
+ table->max_refs *= 2;
+ table->table = (xmlRefPtr *)
+ xmlRealloc(table->table, table->max_refs *
+ sizeof(xmlRefPtr));
+ if (table->table == NULL) {
+ fprintf(stderr, "xmlAddRef: out of memory\n");
+ return(NULL);
+ }
+ }
+ ret = (xmlRefPtr) xmlMalloc(sizeof(xmlRef));
+ if (ret == NULL) {
+ fprintf(stderr, "xmlAddRef: out of memory\n");
+ return(NULL);
+ }
+ table->table[table->nb_refs] = ret;
+
+ /*
+ * fill the structure.
+ */
+ ret->value = xmlStrdup(value);
+ ret->attr = attr;
+ table->nb_refs++;
+
+ return(ret);
+}
+
+/**
+ * xmlFreeRef:
+ * @not: A ref
+ *
+ * Deallocate the memory used by an ref definition
+ */
+void
+xmlFreeRef(xmlRefPtr ref) {
+ if (ref == NULL) return;
+ if (ref->value != NULL)
+ xmlFree((CHAR *) ref->value);
+ memset(ref, -1, sizeof(xmlRef));
+ xmlFree(ref);
+}
+
+/**
+ * xmlFreeRefTable:
+ * @table: An ref table
+ *
+ * Deallocate the memory used by an Ref hash table.
+ */
+void
+xmlFreeRefTable(xmlRefTablePtr table) {
+ int i;
+
+ if (table == NULL) return;
+
+ for (i = 0;i < table->nb_refs;i++) {
+ xmlFreeRef(table->table[i]);
+ }
+ xmlFree(table->table);
+ xmlFree(table);
+}
+
+/**
+ * xmlIsRef
+ * @doc: the document
+ * @elem: the element carrying the attribute
+ * @attr: the attribute
+ *
+ * Determine whether an attribute is of type Ref. In case we have Dtd(s)
+ * then this is simple, otherwise we use an heuristic: name Ref (upper
+ * or lowercase).
+ *
+ * Returns 0 or 1 depending on the lookup result
+ */
+int
+xmlIsRef(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr) {
+ if ((doc->intSubset == NULL) && (doc->extSubset == NULL)) {
+ return(0);
+ /*******************
+ if (((attr->name[0] == 'I') || (attr->name[0] == 'i')) &&
+ ((attr->name[1] == 'D') || (attr->name[1] == 'd')) &&
+ (attr->name[2] == 0)) return(1);
+ *******************/
+ } else {
+ xmlAttributePtr attrDecl;
+
+ attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, attr->name);
+ if ((attrDecl == NULL) && (doc->extSubset != NULL))
+ attrDecl = xmlGetDtdAttrDesc(doc->extSubset, elem->name,
+ attr->name);
+
+ if ((attrDecl != NULL) && (attrDecl->type == XML_ATTRIBUTE_IDREF))
+ return(1);
+ }
+ return(0);
+}
+
+/**
+ * xmlGetRef:
+ * @doc: pointer to the document
+ * @Ref: the Ref value
+ *
+ * Search the attribute declaring the given Ref
+ *
+ * Returns NULL if not found, otherwise the xmlAttrPtr defining the Ref
+ */
+xmlAttrPtr
+xmlGetRef(xmlDocPtr doc, const CHAR *Ref) {
+ xmlRefPtr cur;
+ xmlRefTablePtr table;
+ int i;
+
+ if (doc == NULL) {
+ fprintf(stderr, "xmlGetRef: doc == NULL\n");
+ return(NULL);
+ }
+
+ if (Ref == NULL) {
+ fprintf(stderr, "xmlGetRef: Ref == NULL\n");
+ return(NULL);
+ }
+
+ table = doc->refs;
+ if (table == NULL)
+ return(NULL);
+
+ /*
+ * Search the Ref list.
+ */
+ for (i = 0;i < table->nb_refs;i++) {
+ cur = table->table[i];
+ if (!xmlStrcmp(cur->value, Ref)) {
+ return(cur->attr);
+ }
+ }
+ return(NULL);
+}
+
+/************************************************************************
+ * *
* Routines for validity checking *
* *
************************************************************************/
@@ -2165,6 +2387,10 @@
xmlAddID(ctxt, doc, value, attr);
}
+ if (attrDecl->type == XML_ATTRIBUTE_IDREF) {
+ xmlAddRef(ctxt, doc, value, attr);
+ }
+
/* Validity Constraint: Notation Attributes */
if (attrDecl->type == XML_ATTRIBUTE_NOTATION) {
xmlEnumerationPtr tree = attrDecl->tree;
@@ -2610,9 +2836,75 @@
int
xmlValidateElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem) {
+ xmlNodePtr child;
+ xmlAttrPtr attr;
+ CHAR *value;
+ int ret = 1;
+
+ /* TODO xmlValidateElement */
+
+ if (elem == NULL) return(0);
CHECK_DTD;
- return(1);
+ ret &= xmlValidateOneElement(ctxt, doc, elem);
+ attr = elem->properties;
+ while(attr != NULL) {
+ value = xmlNodeListGetString(doc, attr->val, 0);
+ ret &= xmlValidateOneAttribute(ctxt, doc, elem, attr, value);
+ if (value != NULL)
+ free(value);
+ attr= attr->next;
+ }
+ child = elem->childs;
+ while (child != NULL) {
+ ret &= xmlValidateElement(ctxt, doc, child);
+ child = child->next;
+ }
+
+ return(ret);
+}
+
+/**
+ * xmlValidateDocumentFinal:
+ * @ctxt: the validation context
+ * @doc: a document instance
+ *
+ * Does the final step for the document validation once all the
+ * incremental validation steps have been completed
+ *
+ * basically it does the following checks described by the XML Rec
+ *
+ *
+ * returns 1 if valid or 0 otherwise
+ */
+
+int
+xmlValidateDocumentFinal(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
+ int ret = 1, i;
+ xmlRefTablePtr table;
+ xmlAttrPtr id;
+
+ if (doc == NULL) {
+ fprintf(stderr, "xmlValidateDocumentFinal: doc == NULL\n");
+ return(0);
+ }
+
+ /*
+ * Get the refs table
+ */
+ 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;
+ }
+ }
+ }
+ return(ret);
}
/**
@@ -2630,6 +2922,7 @@
int
xmlValidateDtd(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlDtdPtr dtd) {
+ /* TODO xmlValidateDtd */
return(1);
}
@@ -2640,7 +2933,7 @@
*
* Try to validate the document instance
*
- * basically it does the all the checks described by the
+ * basically it does the all the checks described by the XML Rec
* i.e. validates the internal and external subset (if present)
* and validate the document tree.
*
@@ -2649,8 +2942,12 @@
int
xmlValidateDocument(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
+ int ret;
+
if (!xmlValidateRoot(ctxt, doc)) return(0);
- return(1);
+ ret = xmlValidateElement(ctxt, doc, doc->root);
+ ret &= xmlValidateDocumentFinal(ctxt, doc);
+ return(ret);
}
diff --git a/valid.h b/valid.h
index 37b4f99..22a2c27 100644
--- a/valid.h
+++ b/valid.h
@@ -88,6 +88,20 @@
} xmlIDTable;
typedef xmlIDTable *xmlIDTablePtr;
+/*
+ * ALl Refs attributes are stored in a table
+ * there is one table per document
+ */
+
+#define XML_MIN_REF_TABLE 32
+
+typedef struct xmlRefTable {
+ int nb_refs; /* number of refs stored */
+ int max_refs; /* maximum number of refs */
+ xmlRefPtr *table; /* the table of refs */
+} xmlRefTable;
+typedef xmlRefTable *xmlRefTablePtr;
+
/* Notation */
xmlNotationPtr xmlAddNotationDecl (xmlValidCtxtPtr ctxt,
xmlDtdPtr dtd,
@@ -148,6 +162,17 @@
xmlNodePtr elem,
xmlAttrPtr attr);
+/* IDREFs */
+xmlRefPtr xmlAddRef (xmlValidCtxtPtr ctxt,
+ xmlDocPtr doc,
+ const CHAR *value,
+ xmlAttrPtr attr);
+xmlRefTablePtr xmlCopyRefTable (xmlRefTablePtr table);
+void xmlFreeRefTable (xmlRefTablePtr table);
+int xmlIsRef (xmlDocPtr doc,
+ xmlNodePtr elem,
+ xmlAttrPtr attr);
+
/**
* The public function calls related to validity checking
*/
@@ -181,6 +206,8 @@
xmlNodePtr elem,
xmlAttrPtr attr,
const CHAR *value);
+int xmlValidateDocumentFinal(xmlValidCtxtPtr ctxt,
+ xmlDocPtr doc);
int xmlValidateNotationUse (xmlValidCtxtPtr ctxt,
xmlDocPtr doc,
const CHAR *notationName);
diff --git a/xpath.c b/xpath.c
index 4ff7da5..a0f6a2a 100644
--- a/xpath.c
+++ b/xpath.c
@@ -769,7 +769,7 @@
* Returns the xmlXPathContext just allocated.
*/
xmlXPathContextPtr
-xmlXPathNewContext(xmlDocPtr doc, void *variables, void *functions) {
+xmlXPathNewContext(xmlDocPtr doc) {
xmlXPathContextPtr ret;
ret = (xmlXPathContextPtr) xmlMalloc(sizeof(xmlXPathContext));
@@ -779,9 +779,25 @@
}
memset(ret, 0 , (size_t) sizeof(xmlXPathContext));
ret->doc = doc;
- ret->variables = variables;
- ret->functions = functions;
+
+ ret->nb_variables = 0;
+ ret->max_variables = 0;
+ ret->variables = NULL;
+
+ ret->nb_types = 0;
+ ret->max_types = 0;
+ ret->types = NULL;
+
+ ret->nb_funcs = 0;
+ ret->max_funcs = 0;
+ ret->funcs = NULL;
+
+ ret->nb_axis = 0;
+ ret->max_axis = 0;
+ ret->axis = NULL;
+
ret->namespaces = NULL;
+ ret->user = NULL;
ret->nsNr = 0;
return(ret);
}
diff --git a/xpath.h b/xpath.h
index 6408503..d46c063 100644
--- a/xpath.h
+++ b/xpath.h
@@ -14,6 +14,8 @@
#include "tree.h"
+typedef struct xmlXPathParserContext *xmlXPathParserContextPtr;
+
/*
* A node-set (an unordered collection of nodes without duplicates)
*/
@@ -37,6 +39,7 @@
#define XPATH_BOOLEAN 2
#define XPATH_NUMBER 3
#define XPATH_STRING 4
+#define XPATH_USERS 5
typedef struct xmlXPathObject {
int type;
@@ -44,8 +47,66 @@
int boolval;
double floatval;
CHAR *stringval;
+ void *user;
} xmlXPathObject, *xmlXPathObjectPtr;
+/*
+ * A conversion function is associated to a type and used to cast
+ * the new type to primitive values.
+ */
+typedef int (*xmlXPathConvertFunc) (xmlXPathObjectPtr obj, int type);
+
+/*
+ * Extra type: a name and a conversion function.
+ */
+
+typedef struct xmlXPathType {
+ const CHAR *name; /* the type name */
+ xmlXPathConvertFunc func; /* the conversion function */
+} xmlXPathType, *xmlXPathTypePtr;
+
+/*
+ * Extra variable: a name and a value.
+ */
+
+typedef struct xmlXPathVariable {
+ const CHAR *name; /* the variable name */
+ xmlXPathObjectPtr value; /* the value */
+} xmlXPathVariable, *xmlXPathVariablePtr;
+
+/*
+ * an evaluation function, the parameters are on the context stack
+ */
+
+typedef void (*xmlXPathEvalFunc)(xmlXPathParserContextPtr ctxt, int nargs);
+
+/*
+ * Extra function: a name and a evaluation function.
+ */
+
+typedef struct xmlXPathFunct {
+ const CHAR *name; /* the function name */
+ xmlXPathEvalFunc func; /* the evaluation function */
+} xmlXPathFunc, *xmlXPathFuncPtr;
+
+/*
+ * An axis traversal function. To traverse an axis, the engine calls
+ * the first time with cur == NULL and repeat until the function returns
+ * NULL indicating the end of the axis traversal.
+ */
+
+typedef xmlXPathObjectPtr (*xmlXPathAxisFunc) (xmlXPathParserContextPtr ctxt,
+ xmlXPathObjectPtr cur);
+
+/*
+ * Extra axis: a name and an axis function.
+ */
+
+typedef struct xmlXPathAxis {
+ const CHAR *name; /* the axis name */
+ xmlXPathAxisFunc func; /* the search function */
+} xmlXPathAxis, *xmlXPathAxisPtr;
+
/*
* Expression evaluation occurs with respect to a context.
* he context consists of:
@@ -60,10 +121,27 @@
xmlDocPtr doc; /* The current document */
xmlNodePtr node; /* The current node */
xmlNodeSetPtr nodelist; /* The current node list */
- void *variables; /* TODO !!!! */
- void *functions; /* TODO !!!! */
+
+ int nb_variables; /* number of defined variables */
+ int max_variables; /* max number of variables */
+ xmlXPathVariablePtr *variables; /* Array of defined variables */
+
+ int nb_types; /* number of defined types */
+ int max_types; /* max number of types */
+ xmlXPathTypePtr *types; /* Array of defined types */
+
+ int nb_funcs; /* number of defined funcs */
+ int max_funcs; /* max number of funcs */
+ xmlXPathFuncPtr *funcs; /* Array of defined funcs */
+
+ int nb_axis; /* number of defined axis */
+ int max_axis; /* max number of axis */
+ xmlXPathAxisPtr *axis; /* Array of defined axis */
+
+ /* Namespace traversal should be implemented with user */
xmlNsPtr *namespaces; /* The namespaces lookup */
int nsNr; /* the current Namespace index */
+ void *user; /* user defined extra info */
} xmlXPathContext, *xmlXPathContextPtr;
/*
@@ -81,7 +159,7 @@
int valueNr; /* number of values stacked */
int valueMax; /* max number of values stacked */
xmlXPathObjectPtr *valueTab; /* stack of values */
-} xmlXPathParserContext, *xmlXPathParserContextPtr;
+} xmlXPathParserContext;
/*
* An XPath function
@@ -97,9 +175,26 @@
* *
************************************************************************/
-xmlXPathContextPtr xmlXPathNewContext (xmlDocPtr doc,
- void *variables,
- void *functions);
+/**
+ * Registering extensions to the expression language
+ */
+/* TODO */ int xmlXPathRegisterType (xmlXPathContextPtr ctxt,
+ const CHAR *name,
+ xmlXPathConvertFunc f);
+/* TODO */ int xmlXPathRegisterAxis (xmlXPathContextPtr ctxt,
+ const CHAR *name,
+ xmlXPathAxisFunc f);
+/* TODO */ int xmlXPathRegisterFunc (xmlXPathContextPtr ctxt,
+ const CHAR *name,
+ xmlXPathFunction f);
+/* TODO */ int xmlXPathRegisterVariable (xmlXPathContextPtr ctxt,
+ const CHAR *name,
+ xmlXPathObject value);
+
+/**
+ * Evaluation functions.
+ */
+xmlXPathContextPtr xmlXPathNewContext (xmlDocPtr doc);
void xmlXPathFreeContext (xmlXPathContextPtr ctxt);
xmlXPathObjectPtr xmlXPathEval (const CHAR *str,
xmlXPathContextPtr ctxt);