move the TODO as comments as the function while not finished are usable
* xmlsave.c: move the TODO as comments as the function while not
finished are usable as-is
* xmlschemas.c include/libxml/xmlerror.h: patch from Kasimier Buchcik
implementing union
* test/schemas/union_0_0.x* result/schemas/union_0_0*: added example
* python/Makefile.am: applied fix from Mike Hommey
Daniel
diff --git a/ChangeLog b/ChangeLog
index beb6de3..51dd281 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Fri Apr 16 18:22:25 CEST 2004 Daniel Veillard <daniel@veillard.com>
+
+ * xmlsave.c: move the TODO as comments as the function while not
+ finished are usable as-is
+ * xmlschemas.c include/libxml/xmlerror.h: patch from Kasimier Buchcik
+ implementing union
+ * test/schemas/union_0_0.x* result/schemas/union_0_0*: added example
+ * python/Makefile.am: applied fix from Mike Hommey
+
Fri Apr 16 23:58:42 HKT 2004 William Brack <wbrack@mmm.com.hk>
* parser.c: fixed problem with detecting external dtd
diff --git a/include/libxml/xmlerror.h b/include/libxml/xmlerror.h
index 46d93c4..815000b 100644
--- a/include/libxml/xmlerror.h
+++ b/include/libxml/xmlerror.h
@@ -544,6 +544,7 @@
XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI, /* 1769 */
XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI, /* 1770 */
XML_SCHEMAP_NOT_SCHEMA, /* 1771 */
+ XML_SCHEMAP_UNKNOWN_MEMBER_TYPE, /* 1772 */
XML_SCHEMAV_NOROOT = 1800,
XML_SCHEMAV_UNDECLAREDELEM, /* 1801 */
XML_SCHEMAV_NOTTOPLEVEL, /* 1802 */
diff --git a/python/Makefile.am b/python/Makefile.am
index 8782efb..f473421 100644
--- a/python/Makefile.am
+++ b/python/Makefile.am
@@ -51,9 +51,12 @@
API_DESC = $(top_srcdir)/doc/libxml2-api.xml $(srcdir)/libxml2-python-api.xml
GENERATED= $(srcdir)/libxml2class.py \
$(srcdir)/libxml2-export.c \
+ $(srcdir)/libxml2class.txt \
$(srcdir)/libxml2-py.c \
$(srcdir)/libxml2-py.h
+CLEANFILES= $(GENERATED) gen_prog libxml2.py
+
$(GENERATED): gen_prog
gen_prog: $(srcdir)/$(GENERATE) $(API_DESC)
@@ -68,6 +71,3 @@
tests test: all
cd tests && $(MAKE) tests
-clean:
- rm -f $(GENERATED) *.o _libxml.so *.pyc libxml2.py gen_prog
-
diff --git a/result/schemas/union_0_0 b/result/schemas/union_0_0
new file mode 100644
index 0000000..3dbc861
--- /dev/null
+++ b/result/schemas/union_0_0
@@ -0,0 +1 @@
+./test/schemas/union_0_0.xml validates
diff --git a/result/schemas/union_0_0.err b/result/schemas/union_0_0.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/result/schemas/union_0_0.err
diff --git a/test/schemas/union_0_0.xml b/test/schemas/union_0_0.xml
new file mode 100644
index 0000000..79078f9
--- /dev/null
+++ b/test/schemas/union_0_0.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<foo xmlns="http://foo"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
+ <em>EMP0090</em>
+ <em>EMP0099</em>
+</foo>
+
diff --git a/test/schemas/union_0_0.xsd b/test/schemas/union_0_0.xsd
new file mode 100644
index 0000000..a6dfad0
--- /dev/null
+++ b/test/schemas/union_0_0.xsd
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ targetNamespace="http://foo"
+ xmlns="http://foo"
+ xmlns:a="http://foo">
+
+ <xsd:element name="foo">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="em" type="emType" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:simpleType name="emp0001_3Type">
+ <xsd:restriction base="xsd:ID">
+ <xsd:enumeration value="EMP0040"/>
+ <xsd:enumeration value="EMP0003"/>
+ <xsd:enumeration value="EMP0004"/>
+ <xsd:enumeration value="EMP0005"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="emp0004_5Type">
+ <xsd:restriction base="xsd:ID">
+ <xsd:enumeration value="EMP0002"/>
+ <xsd:enumeration value="EMP0090"/>
+ <xsd:enumeration value="EMP0007"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="unboundedEmType">
+ <xsd:union memberTypes="a:emp0001_3Type emp0004_5Type">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:ID">
+ <xsd:enumeration value="EMP0099"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:union>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="emType">
+ <xsd:restriction base="unboundedEmType">
+ <xsd:pattern value="EMP[0-9]*"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+
+
+</xsd:schema>
diff --git a/xmlsave.c b/xmlsave.c
index 583fb58..1a60a31 100644
--- a/xmlsave.c
+++ b/xmlsave.c
@@ -1265,6 +1265,8 @@
* @doc: a document
*
* Save a full document to a saving context
+ * TODO: The function is not fully implemented yet as it does not return the
+ * byte count but 0 instead
*
* Returns the number of byte written or -1 in case of error
*/
@@ -1274,7 +1276,6 @@
long ret = 0;
xmlDocContentDumpOutput(ctxt, doc);
- TODO /* compute ret */
return(ret);
}
@@ -1284,6 +1285,8 @@
* @node: a document
*
* Save a subtree starting at the node parameter to a saving context
+ * TODO: The function is not fully implemented yet as it does not return the
+ * byte count but 0 instead
*
* Returns the number of byte written or -1 in case of error
*/
@@ -1293,7 +1296,6 @@
long ret = 0;
xmlNodeDumpOutputInternal(ctxt, node);
- TODO /* compute ret */
return(ret);
}
diff --git a/xmlschemas.c b/xmlschemas.c
index 99bf02b..be7b6ae 100644
--- a/xmlschemas.c
+++ b/xmlschemas.c
@@ -2279,7 +2279,7 @@
if (type == NULL)
return (NULL);
type->node = node;
- type->type = XML_SCHEMA_TYPE_LIST;
+ type->type = XML_SCHEMA_TYPE_UNION;
type->id = xmlSchemaGetProp(ctxt, node, "id");
type->ref = xmlSchemaGetProp(ctxt, node, "memberTypes");
@@ -4358,6 +4358,57 @@
}
}
+static void
+xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr typeDecl,
+ xmlSchemaParserCtxtPtr ctxt)
+{
+ const xmlChar *cur, *end, *prefix, *ncName, *namespace;
+ xmlChar *tmp;
+ xmlSchemaTypePtr subtype;
+ xmlNsPtr ns;
+ int len;
+
+ if ((typeDecl->type != XML_SCHEMA_TYPE_UNION) || (typeDecl->ref == NULL))
+ return;
+
+ cur = typeDecl->ref;
+ do {
+ while (IS_BLANK_CH(*cur))
+ cur++;
+ end = cur;
+ while ((*end != 0) && (!(IS_BLANK_CH(*end))))
+ end++;
+ if (end == cur)
+ break;
+ tmp = xmlStrndup(cur, end - cur);
+ ncName = xmlSplitQName3(tmp, &len);
+ if (ncName != NULL) {
+ prefix = xmlDictLookup(ctxt->dict, tmp, len);
+ } else {
+ prefix = NULL;
+ ncName = tmp;
+ }
+ ns = xmlSearchNs(typeDecl->node->doc, typeDecl->node, prefix);
+ if (ns == NULL) {
+ xmlSchemaPErr(ctxt, typeDecl->node, XML_SCHEMAP_PREFIX_UNDEFINED,
+ "Union %s: the namespace of member type %s is undefined\n",
+ typeDecl->name, (const char *) tmp);
+ } else {
+ namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
+ }
+ /* Lookup the referenced type */
+ subtype = xmlSchemaGetType(ctxt->schema, ncName, namespace);
+ if (subtype == NULL) {
+ xmlSchemaPErr(ctxt, typeDecl->node, XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
+ "Union %s references an unknown member type >%s<\n",
+ typeDecl->name, (const char *) tmp);
+ }
+ xmlFree(tmp);
+ cur = end;
+ } while (*cur != 0);
+
+}
+
/**
* xmlSchemaTypeFixup:
* @typeDecl: the schema type definition
@@ -4553,6 +4604,7 @@
case XML_SCHEMA_TYPE_NOTATION:
case XML_SCHEMA_TYPE_LIST:
case XML_SCHEMA_TYPE_UNION:
+ xmlSchemaParseUnionRefCheck(typeDecl, ctxt);
case XML_SCHEMA_FACET_MININCLUSIVE:
case XML_SCHEMA_FACET_MINEXCLUSIVE:
case XML_SCHEMA_FACET_MAXINCLUSIVE:
@@ -5077,6 +5129,28 @@
xmlSchemaTypePtr base,
xmlSchemaFacetPtr facets, const xmlChar * value)
{
+ return(xmlSchemaValidateFacetsInternal(ctxt, base, facets, value, 1));
+}
+
+/**
+ * xmlSchemaValidateFacetsInternal:
+ * @ctxt: a schema validation context
+ * @base: the base type
+ * @facets: the list of facets to check
+ * @value: the lexical repr of the value to validate
+ * @val: the precomputed value
+ * @fireErrors: if 0, only internal errors will be fired; otherwise all errors will be fired.
+ *
+ * Check a value against all facet conditions
+ *
+ * Returns 0 if the element is schemas valid, a positive error code
+ * number otherwise and -1 in case of internal or API error.
+ */
+static int
+xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
+ xmlSchemaTypePtr base,
+ xmlSchemaFacetPtr facets, const xmlChar * value, int fireErrors)
+{
int ret = 0;
int tmp = 0;
xmlSchemaTypeType type;
@@ -5101,7 +5175,8 @@
if (tmp != 0) {
ret = tmp;
- xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_FACET, "Failed to validate type with facet %s\n", (const xmlChar *) xmlSchemaFacetTypeToString(type), NULL);
+ if (fireErrors)
+ xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_FACET, "Failed to validate type with facet %s\n", (const xmlChar *) xmlSchemaFacetTypeToString(type), NULL);
}
if (facet != NULL)
facet = facet->next;
@@ -5116,6 +5191,76 @@
************************************************************************/
/**
+ * xmlSchemaValidateSimpleValueUnion:
+ * @ctxt: a schema validation context
+ * @type: the type declaration
+ * @value: the value to validate
+ *
+ * Validates a value against a union.
+ *
+ * Returns 0 if the value is valid, a positive error code
+ * number otherwise and -1 in case of internal or API error.
+ */
+static int
+xmlSchemaValidateSimpleValueUnion(xmlSchemaValidCtxtPtr ctxt,
+ xmlSchemaTypePtr type, const xmlChar * value)
+{
+ int ret = 0;
+ const xmlChar *cur, *end, *prefix, *ncName;
+ xmlChar *tmp;
+ xmlSchemaTypePtr subtype;
+ xmlNsPtr ns;
+ int len;
+
+
+ /* Process referenced memberTypes. */
+ cur = type->ref;
+ do {
+ while (IS_BLANK_CH(*cur))
+ cur++;
+ end = cur;
+ while ((*end != 0) && (!(IS_BLANK_CH(*end))))
+ end++;
+ if (end == cur)
+ break;
+ tmp = xmlStrndup(cur, end - cur);
+ ncName = xmlSplitQName3(tmp, &len);
+ if (ncName != NULL) {
+ prefix = xmlStrndup(tmp, len);
+ /* prefix = xmlDictLookup(ctxt->doc->dict, tmp, len); */
+ } else {
+ prefix = NULL;
+ ncName = tmp;
+ }
+ /* We won't do additional checks here, since they have been performed during parsing. */
+ ns = xmlSearchNs(type->node->doc, type->node, prefix);
+ /* namespace = xmlDictLookup(ctxt->doc->dict, ns->href, -1); */
+ subtype = xmlSchemaGetType(ctxt->schema, ncName, ns->href);
+ if (tmp != NULL)
+ xmlFree(tmp);
+ if (prefix != NULL)
+ xmlFree(prefix);
+ ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
+ if ((ret == 0) || (ret == -1)) {
+ return (ret);
+ }
+ cur = end;
+ } while (*cur != 0);
+
+ if (type->subtypes != NULL) {
+ subtype = type->subtypes;
+ do {
+ ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
+ if ((ret == 0) || (ret == -1)) {
+ return (ret);
+ }
+ subtype = subtype->next;
+ } while (subtype != NULL);
+ }
+ return (ret);
+}
+
+/**
* xmlSchemaValidateSimpleValue:
* @ctxt: a schema validation context
* @type: the type declaration
@@ -5130,6 +5275,25 @@
xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
xmlSchemaTypePtr type, const xmlChar * value)
{
+ return (xmlSchemaValidateSimpleValueInternal(ctxt, type, value, 1));
+}
+
+/**
+ * xmlSchemaValidateSimpleValue:
+ * @ctxt: a schema validation context
+ * @type: the type declaration
+ * @value: the value to validate
+ * @fireErrors: if 0, only internal errors will be fired; otherwise all errors will be fired.
+ *
+ * Validate a value against a simple type
+ *
+ * Returns 0 if the value is valid, a positive error code
+ * number otherwise and -1 in case of internal or API error.
+ */
+static int
+xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
+ xmlSchemaTypePtr type, const xmlChar * value, int fireErrors)
+{
int ret = 0;
/*
@@ -5147,7 +5311,7 @@
}
ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
ctxt->cur);
- if (ret != 0) {
+ if ((fireErrors) && (ret != 0)) {
xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE, "Failed to validate basic type %s\n", type->name, NULL);
}
} else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
@@ -5156,7 +5320,7 @@
base = type->baseType;
if (base != NULL) {
- ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
+ ret = xmlSchemaValidateSimpleValueInternal(ctxt, base, value, fireErrors);
} else if (type->subtypes != NULL) {
TODO
}
@@ -5168,7 +5332,7 @@
if (ctxt->schema != NULL) {
if (ret == 0) {
facet = type->facets;
- ret = xmlSchemaValidateFacets(ctxt, base, facet, value);
+ ret = xmlSchemaValidateFacetsInternal(ctxt, base, facet, value, fireErrors);
}
}
} else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
@@ -5176,7 +5340,7 @@
base = type->subtypes;
if (base != NULL) {
- ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
+ ret = xmlSchemaValidateSimpleValueInternal(ctxt, base, value, fireErrors);
} else {
TODO}
} else if (type->type == XML_SCHEMA_TYPE_LIST) {
@@ -5202,12 +5366,17 @@
if (end == cur)
break;
tmp = xmlStrndup(cur, end - cur);
- ret2 = xmlSchemaValidateSimpleValue(ctxt, base, tmp);
+ ret2 = xmlSchemaValidateSimpleValueInternal(ctxt, base, tmp, fireErrors);
xmlFree(tmp);
if (ret2 != 0)
ret = 1;
cur = end;
} while (*cur != 0);
+ } else if (type->type == XML_SCHEMA_TYPE_UNION) {
+ ret = xmlSchemaValidateSimpleValueUnion(ctxt, type, value);
+ if ((fireErrors) && (ret != 0)) {
+ xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE, "Failed to validate type %s\n", type->name, NULL);
+ }
} else {
TODO
}