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
     }