fixed validation of attribute groups. added an example from the primer

* xmlschemas.c: fixed validation of attribute groups.
* test/schemas result/schemas: added an example from the primer
Daniel
diff --git a/ChangeLog b/ChangeLog
index 661a51c..5160be6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Tue Apr 23 19:50:40 CEST 2002 Daniel Veillard <daniel@veillard.com>
+
+	* xmlschemas.c: fixed validation of attribute groups.
+	* test/schemas result/schemas: added an example from the primer
+
 Tue Apr 23 09:11:37 CEST 2002 Daniel Veillard <daniel@veillard.com>
 
 	* Makefile.am xmlschemas.c xmlschemastypes.c: more work on Schemas
diff --git a/include/libxml/schemasInternals.h b/include/libxml/schemasInternals.h
index e59e157..bb8c9a4 100644
--- a/include/libxml/schemasInternals.h
+++ b/include/libxml/schemasInternals.h
@@ -44,6 +44,7 @@
     XML_SCHEMA_TYPE_EXTENSION,
     XML_SCHEMA_TYPE_ELEMENT,
     XML_SCHEMA_TYPE_ATTRIBUTE,
+    XML_SCHEMA_TYPE_ATTRIBUTEGROUP,
     XML_SCHEMA_TYPE_GROUP,
     XML_SCHEMA_TYPE_NOTATION,
     XML_SCHEMA_TYPE_LIST,
diff --git a/result/schemas/item_1_0 b/result/schemas/item_1_0
new file mode 100644
index 0000000..90fa561
--- /dev/null
+++ b/result/schemas/item_1_0
@@ -0,0 +1 @@
+./test/schemas/item_0.xml validates
diff --git a/result/schemas/item_1_0.err b/result/schemas/item_1_0.err
new file mode 100644
index 0000000..1c5674e
--- /dev/null
+++ b/result/schemas/item_1_0.err
@@ -0,0 +1,39 @@
+Type of sequence 3 : ./test/schemas/item_1.xsd:12 :elements
+Type of restriction 5 : ./test/schemas/item_1.xsd:16 :empty
+Type of simpletype4 : ./test/schemas/item_1.xsd:15 :simple
+Type of SKU : ./test/schemas/item_1.xsd:5 :simple
+Type of restriction 9 : ./test/schemas/item_1.xsd:34 :empty
+Type of simpletype8 : ./test/schemas/item_1.xsd:33 :simple
+Type of restriction 1 : ./test/schemas/item_1.xsd:6 :empty
+Type of sequence 3 : ./test/schemas/item_1.xsd:12 :elements
+Type of anontype2 : ./test/schemas/item_1.xsd:11 :elements
+Building content model for Item
+Content model of Item:
+ regexp: '(null)' 
+5 atoms:
+ 00  atom: string once 'productName' 
+ 01  atom: string once 'quantity' 
+ 02  atom: string once 'USPrice' 
+ 03  atom: string once 'comment' 
+ 04  atom: string once 'shipDate' 
+6 states:
+ state: 0, 1 transitions:
+  trans: atom 0, to 1
+ state: 1, 1 transitions:
+  trans: atom 1, to 2
+ state: 2, 1 transitions:
+  trans: atom 2, to 3
+ state: FINAL 3, 3 transitions:
+  trans: atom 3, to 4
+  trans: removed
+  trans: atom 4, to 5
+ state: FINAL 4, 2 transitions:
+  trans: atom 4, to 5
+  trans: removed
+ state: FINAL 5, 0 transitions:
+0 counters:
+xmlSchemaValidateCallback: productName, productName, productName
+xmlSchemaValidateCallback: quantity, quantity, quantity
+xmlSchemaValidateCallback: USPrice, USPrice, USPrice
+xmlSchemaValidateCallback: comment, comment, comment
+Element Item content check succeeded
diff --git a/test/schemas/item_1.xsd b/test/schemas/item_1.xsd
new file mode 100644
index 0000000..cea1f01
--- /dev/null
+++ b/test/schemas/item_1.xsd
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <xsd:element name="comment" type="xsd:string"/>
+<!-- Stock Keeping Unit, a code for identifying products -->
+  <xsd:simpleType name="SKU">
+    <xsd:restriction base="xsd:string">
+      <xsd:pattern value="\d{3}-[A-Z]{2}"/>
+    </xsd:restriction>
+  </xsd:simpleType>
+  <xsd:element name="Item" minOccurs="0" maxOccurs="unbounded">
+    <xsd:complexType>
+      <xsd:sequence>
+        <xsd:element name="productName" type="xsd:string"/>
+        <xsd:element name="quantity">
+          <xsd:simpleType>
+            <xsd:restriction base="xsd:positiveInteger">
+              <xsd:maxExclusive value="100"/>
+            </xsd:restriction>
+          </xsd:simpleType>
+        </xsd:element>
+        <xsd:element name="USPrice" type="xsd:decimal"/>
+        <xsd:element ref="comment" minOccurs="0"/>
+        <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
+      </xsd:sequence>
+<!-- attributeGroup replaces individual declarations -->
+      <xsd:attributeGroup ref="ItemDelivery"/>
+    </xsd:complexType>
+  </xsd:element>
+  <xsd:attributeGroup name="ItemDelivery">
+    <xsd:attribute name="partNum" type="SKU" use="required"/>
+    <xsd:attribute name="weightKg" type="xsd:decimal"/>
+    <xsd:attribute name="shipBy">
+      <xsd:simpleType>
+        <xsd:restriction base="xsd:string">
+          <xsd:enumeration value="air"/>
+          <xsd:enumeration value="land"/>
+          <xsd:enumeration value="any"/>
+        </xsd:restriction>
+      </xsd:simpleType>
+    </xsd:attribute>
+  </xsd:attributeGroup>
+</xsd:schema>
diff --git a/xmlschemas.c b/xmlschemas.c
index 86359ce..38b92d3 100644
--- a/xmlschemas.c
+++ b/xmlschemas.c
@@ -1662,6 +1662,7 @@
     }
     ret->ref = ref;
     ret->refNs = refNs;
+    ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
     child = node->children;
     ctxt->container = name;
     if (IS_SCHEMA(child, "annotation")) {
@@ -3554,6 +3555,45 @@
 }
 
 /**
+ * xmlSchemaAttrGrpFixup:
+ * @attrgrpDecl:  the schema attribute definition
+ * @ctxt:  the schema parser context
+ * @name:  the attribute name
+ *
+ * Fixes finish doing the computations on the attributes definitions
+ */
+static void
+xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrpDecl,
+		   xmlSchemaParserCtxtPtr ctxt,
+		   const xmlChar *name)
+{
+    if (name == NULL)
+	name = attrgrpDecl->name;
+    if (attrgrpDecl->attributes != NULL)
+	return;
+    if (attrgrpDecl->ref != NULL) {
+	xmlSchemaAttributeGroupPtr ref;
+
+	ref = xmlHashLookup2(ctxt->schema->attrgrpDecl, attrgrpDecl->ref,
+		             attrgrpDecl->refNs);
+	if (ref == NULL) {
+	    if ((ctxt != NULL) && (ctxt->error != NULL))
+		ctxt->error(ctxt->userData,
+		    "Schemas: attribute group %s reference %s not found\n",
+			    name, attrgrpDecl->ref);
+	    return;
+	}
+	xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
+	attrgrpDecl->attributes = ref->attributes;
+    } else {
+	if ((ctxt != NULL) && (ctxt->error != NULL))
+	    ctxt->error(ctxt->userData,
+		"Schemas: attribute %s has no attributes nor reference\n",
+			name);
+    }
+}
+
+/**
  * xmlSchemaAttrFixup:
  * @attrDecl:  the schema attribute definition
  * @ctxt:  the schema parser context
@@ -3749,6 +3789,11 @@
      */
     xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
 
+    /*
+     * Then fixup all attributes group declarations
+     */
+    xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup, ctxt);
+
     return (ret);
 }
  
@@ -4796,10 +4841,20 @@
     int i, ret;
     xmlAttrPtr attr;
     xmlChar *value;
+    xmlSchemaAttributeGroupPtr group = NULL;
 
     if (attributes == NULL)
 	return(0);
     while (attributes != NULL) {
+	/*
+	 * Handle attribute groups
+	 */
+	if (attributes->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
+	    group = (xmlSchemaAttributeGroupPtr) attributes;
+	    xmlSchemaValidateAttributes(ctxt, elem, group->attributes);
+	    attributes = group->next;
+	    continue;
+	}
 	for (i = ctxt->attrBase;i < ctxt->attrNr;i++) {
 	    attr = ctxt->attr[i].attr;
 	    if (attr == NULL)
@@ -4822,7 +4877,7 @@
 	    }
 	    value = xmlNodeListGetString(elem->doc, attr->children, 1);
 	    ret = xmlSchemaValidateSimpleValue(ctxt, attributes->subtypes,
-		                               value);
+					       value);
 	    if (ret != 0) {
 		ctxt->err = XML_SCHEMAS_ERR_ATTRINVALID;
 		if (ctxt->error != NULL)