Commit 50355f00 authored by Daniel Veillard's avatar Daniel Veillard
Browse files

applied another patch from Kasimier Buchcik for Schema Component

* xmlschemas.c include/libxml/xmlerror.h: applied another patch
  from Kasimier Buchcik for Schema Component Constraints
* test/schemas/* result/schemas/*: added the regression tests
Daniel
parent 8304d87d
Tue Jun 8 19:50:25 CEST 2004 Daniel Veillard <daniel@veillard.com>
* xmlschemas.c include/libxml/xmlerror.h: applied another patch
from Kasimier Buchcik for Schema Component Constraints
* test/schemas/* result/schemas/*: added the regression tests
Tue Jun 8 21:27:03 HKT 2004 William Brack <wbrack@mmm.com.hk>
 
* xmllint.c: fixed missing error return code for schema
......
......@@ -570,6 +570,10 @@ typedef enum {
XML_SCHEMAP_UNION_NOT_EXPRESSIBLE, /* 1793 */
XML_SCHEMAP_SRC_IMPORT_3_1, /* 1794 */
XML_SCHEMAP_SRC_IMPORT_3_2, /* 1795 */
XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1, /* 1796 */
XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2, /* 1797 */
XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3, /* 1798 */
XML_SCHEMAP_COS_CT_EXTENDS_1_3, /* 1799 */
XML_SCHEMAV_NOROOT = 1800,
XML_SCHEMAV_UNDECLAREDELEM, /* 1801 */
XML_SCHEMAV_NOTTOPLEVEL, /* 1802 */
......
./test/schemas/anyAttr-derive2_0.xml validates
./test/schemas/cos-ct-extends-1-3_0.xml validates
./test/schemas/derivation-ok-restriction-4-1-err_0.xsd:33: element complexType: Schemas parser error : The derived type "type.A" has an attribute wildcard, but the base type "base.type.A" does not have one.
./test/schemas/derivation-ok-restriction-4-1-err_0.xsd:45: element complexType: Schemas parser error : The wildcard in the derived type "type.B" is not a valid subset of the one in the base type "base.type.B".
./test/schemas/derivation-ok-restriction-4-1-err_0.xsd:57: element complexType: Schemas parser error : The process contents of the wildcard in the derived type "type.C" is weaker than that in the base type "base.type.C".
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
-->
<foo xmlns="http://FOO" xmlns:foo="http://FOO" xmlns:bar="http://BAR" xmlns:boo="http://BOO" xmlns:doo="http://DOO"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://FOO attrGroup-wildcard1_0.xsd"
foo:bar="o" doo:bar="o"/>
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!--
-->
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://FOO"
xmlns:foo="http://FOO" elementFormDefault="qualified" attributeFormDefault="qualified">
<element name="foo">
<complexType>
<complexContent>
<extension base="foo:type.A">
<anyAttribute namespace="http://DOO" processContents="skip"/>
</extension>
</complexContent>
</complexType>
</element>
<complexType name="type.A">
<attributeGroup ref="foo:attrGr.A_1"/>
<attributeGroup ref="foo:attrGr.A_2"/>
<anyAttribute namespace="http://FOO" processContents="skip"/>
</complexType>
<attributeGroup name="attrGr.A_1">
<anyAttribute namespace="http://FOO http://BOO" processContents="skip"/>
</attributeGroup>
<attributeGroup name="attrGr.A_2">
<anyAttribute namespace="http://BAR http://DOO http://FOO" processContents="skip"/>
</attributeGroup>
</schema>
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
-->
<foo xmlns="http://FOO" xmlns:foo="http://FOO"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://FOO cos-ct-extends-1-3_0.xsd">
<bar.A foo:bar="o"/>
<bar.B foo:bar="o"/>
</foo>
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!--
Schema Component Constraint: Derivation Valid (Extension)
1.3 If it has an {attribute wildcard}, the complex type definition must
also have one, and the base type definition's {attribute wildcard}'s
{namespace constraint} must be a subset of the complex type definition's
{attribute wildcard}'s {namespace constraint}, as defined by Wildcard Subset (3.10.6).
-->
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://FOO"
xmlns:foo="http://FOO"
elementFormDefault="qualified">
<element name="foo">
<complexType>
<sequence>
<element name="bar.A" type="foo:type.A" />
<element name="bar.B" type="foo:type.B" />
</sequence>
</complexType>
</element>
<complexType name="type.A">
<complexContent>
<!-- This is OK, since the complete wildcard
is the wildcard of the base type. -->
<extension base="foo:base.type.A" />
</complexContent>
</complexType>
<complexType name="base.type.A">
<anyAttribute namespace="##any" processContents="skip" />
</complexType>
<complexType name="type.B">
<complexContent>
<extension base="foo:base.type.B">
<!-- This is OK, since the complete wildcard is a union
of "##any" and "http://FOO" = "##any". Thus the complete
wildcard is equal to that one in the base class. -->
<anyAttribute namespace="http://FOO" processContents="skip" />
</extension>
</complexContent>
</complexType>
<complexType name="base.type.B">
<anyAttribute namespace="##any" processContents="skip" />
</complexType>
</schema>
<?xml version="1.0" encoding="ISO-8859-1"?>
<foo xmlns="http://FOO" xmlns:foo="http://FOO"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://FOO derivation-ok-restriction-4-1-err_0.xsd">
<bar.A />
<bar.B />
<bar.C />
</foo>
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!--
Schema Component Constraint: Derivation Valid (Restriction, Complex)
4 If there is an {attribute wildcard}, all of the following must be true:
4.1 The {base type definition} must also have one.
4.2 The complex type definition's {attribute wildcard}'s {namespace constraint}
must be a subset of the {base type definition}'s {attribute wildcard}'s {namespace
constraint}, as defined by Wildcard Subset (3.10.6).
4.3 Unless the {base type definition} is the ur-type definition, the complex type
definition's {attribute wildcard}'s {process contents} must be identical to or stronger
than the {base type definition}'s {attribute wildcard}'s {process contents},
where strict is stronger than lax is stronger than skip.
-->
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://FOO"
xmlns:foo="http://FOO"
>
<element name="foo">
<complexType>
<sequence>
<element name="bar.A" type="foo:type.A" />
<element name="bar.B" type="foo:type.B" />
<element name="bar.C" type="foo:type.C" />
</sequence>
</complexType>
</element>
<complexType name="type.A">
<complexContent>
<restriction base="foo:base.type.A">
<anyAttribute namespace="##any" processContents="skip" />
</restriction>
</complexContent>
</complexType>
<complexType name="base.type.A">
<attribute name="bar" type="string"/>
</complexType>
<complexType name="type.B">
<complexContent>
<restriction base="foo:base.type.B">
<anyAttribute namespace="##any" processContents="skip" />
</restriction>
</complexContent>
</complexType>
<complexType name="base.type.B">
<anyAttribute namespace="http://FOO" processContents="skip" />
</complexType>
<complexType name="type.C">
<complexContent>
<restriction base="foo:base.type.C">
<anyAttribute namespace="##any" processContents="skip" />
</restriction>
</complexContent>
</complexType>
<complexType name="base.type.C">
<anyAttribute namespace="##any" processContents="lax" />
</complexType>
</schema>
......@@ -5360,6 +5360,16 @@ xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
return (0);
}
/**
* xmlSchemaCloneWildcardNsConstraints:
* @ctxt: the schema parser context
* @dest: the destination wildcard
* @source: the source wildcard
*
* Clones the namespace constraints of source
* and assignes them to dest.
* Returns -1 on internal error, 0 otherwise.
*/
static int
xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
xmlSchemaWildcardPtr *dest,
......@@ -5396,6 +5406,17 @@ xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
return(0);
}
/**
* xmlSchemaUnionWildcards:
* @ctxt: the schema parser context
* @completeWild: the first wildcard
* @curWild: the second wildcard
*
* Unions the namespace constraints of the given wildcards.
* @completeWild will hold the resulting union.
* Returns a positive error code on failure, -1 in case of an
* internal error, 0 otherwise.
*/
static int
xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
xmlSchemaWildcardPtr completeWild,
......@@ -5444,7 +5465,7 @@ xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
/*
* 2 If either O1 or O2 is any, then any must be the value
*/
if ((completeWild->any != curWild->any) && (completeWild->any)) {
if (completeWild->any != curWild->any) {
if (completeWild->any == 0) {
completeWild->any = 1;
if (completeWild->nsSet != NULL) {
......@@ -5456,6 +5477,7 @@ xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
completeWild->negNsSet = NULL;
}
}
return (0);
}
/*
* 3 If both O1 and O2 are sets of (namespace names or absent),
......@@ -5498,6 +5520,8 @@ xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
(curWild->negNsSet != NULL) &&
(completeWild->negNsSet->value != curWild->negNsSet->value)) {
completeWild->negNsSet->value = NULL;
return(0);
}
/*
* 5.
......@@ -5568,7 +5592,7 @@ xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
"The union of the wilcard is not expressible\n",
NULL, NULL);
return(0);
return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
} else if ((!nsFound) && (!absentFound)) {
/*
* 5.4 If the set S does not include either the negated namespace
......@@ -5642,6 +5666,17 @@ xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
}
/**
* xmlSchemaIntersectWildcards:
* @ctxt: the schema parser context
* @completeWild: the first wildcard
* @curWild: the second wildcard
*
* Intersects the namespace constraints of the given wildcards.
* @completeWild will hold the resulting intersection.
* Returns a positive error code on failure, -1 in case of an
* internal error, 0 otherwise.
*/
static int
xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
xmlSchemaWildcardPtr completeWild,
......@@ -5794,7 +5829,7 @@ xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
"The intersection of the wilcard is not expressible\n",
NULL, NULL);
return(0);
return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
}
/*
* 6 If the one is a negation of a namespace name and the other
......@@ -5809,11 +5844,96 @@ xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
return(0);
}
/**
* xmlSchemaIsWildcardNsConstraintSubset:
* @ctxt: the schema parser context
* @wildA: the first wildcard
* @wildB: the second wildcard
*
* Returns 1 if the namespace constraint of @wildA is an intensional
* subset of @wildB, 0 otherwise.
*/
static int
xmlSchemaIsWildcardNsConstraintSubset(
xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
xmlSchemaWildcardPtr wildA,
xmlSchemaWildcardPtr wildB)
{
static xmlSchemaWildcardPtr
xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
xmlSchemaAttributePtr attrs,
xmlSchemaWildcardPtr completeWild)
/*
* Schema Component Constraint: Wildcard Subset
*/
/*
* 1 super must be any.
*/
if (wildB->any)
return (1);
/*
* 2.1 sub must be a pair of not and a namespace name or absent.
* 2.2 super must be a pair of not and the same value.
*/
if ((wildA->negNsSet != NULL) &&
(wildB->negNsSet != NULL) &&
(wildA->negNsSet->value == wildA->negNsSet->value))
return (1);
/*
* 3.1 sub must be a set whose members are either namespace names or absent.
*/
if (wildA->nsSet != NULL) {
/*
* 3.2.1 super must be the same set or a superset thereof.
*/
if (wildB->nsSet != NULL) {
xmlSchemaWildcardNsPtr cur, curB;
int found = 0;
cur = wildA->nsSet;
while (cur != NULL) {
found = 0;
curB = wildB->nsSet;
while (curB != NULL) {
if (cur->value == curB->value) {
found = 1;
break;
}
curB = curB->next;
}
if (!found)
return (0);
cur = cur->next;
}
if (found)
return (1);
} else if (wildB->negNsSet != NULL) {
xmlSchemaWildcardNsPtr cur;
/*
* 3.2.2 super must be a pair of not and a namespace name or
* absent and that value must not be in sub's set.
*/
cur = wildA->nsSet;
while (cur != NULL) {
if (cur->value == wildB->negNsSet->value)
return (0);
cur = cur->next;
}
return (1);
}
}
return (0);
}
/**
* xmlSchemaBuildCompleteAttributeWildcard:
* @ctxt: the schema parser context
* @attrs: the attribute list
* @completeWild: the resulting complete wildcard
*
* Returns -1 in case of an internal error, 0 otherwise.
*/
static int
xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
xmlSchemaAttributePtr attrs,
xmlSchemaWildcardPtr *completeWild)
{
while (attrs != NULL) {
if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
......@@ -5822,44 +5942,39 @@ xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
group = (xmlSchemaAttributeGroupPtr) attrs;
if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
if (group->attributes != NULL) {
if (group->attributeWildcard != NULL)
xmlSchemaBuildCompleteAttributeWildcard(ctxt,
group->attributes, group->attributeWildcard);
else
group->attributeWildcard =
xmlSchemaBuildCompleteAttributeWildcard(ctxt,
group->attributes, group->attributeWildcard);
if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
group->attributes, &group->attributeWildcard) == -1)
return (-1);
}
group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
}
if (group->attributeWildcard != NULL) {
if (completeWild == NULL) {
if (*completeWild == NULL) {
/*
* Copy the first encountered wildcard as context, except for the annotation.
*/
completeWild = xmlSchemaAddWildcard(ctxt);
completeWild->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
if (!xmlSchemaCloneWildcardNsConstraints(ctxt,
&completeWild, group->attributeWildcard))
return(NULL);
completeWild->processContents = group->attributeWildcard->processContents;
*completeWild = xmlSchemaAddWildcard(ctxt);
(*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
if (xmlSchemaCloneWildcardNsConstraints(ctxt,
completeWild, group->attributeWildcard) == -1)
return (-1);
(*completeWild)->processContents = group->attributeWildcard->processContents;
/*
* Although the complete wildcard might not correspond to any
* node in the schema, we will save this context node.
*/
completeWild->node = group->attributeWildcard->node;
return(completeWild);
}
if (xmlSchemaIntersectWildcards(ctxt, completeWild, group->attributeWildcard) == -1) {
xmlSchemaFreeWildcard(completeWild);
return(NULL);
(*completeWild)->node = group->attributeWildcard->node;
} else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
xmlSchemaFreeWildcard(*completeWild);
return (-1);
}
}
}
attrs = attrs->next;
}
return (completeWild);
return (0);
}
/**
......@@ -5911,7 +6026,7 @@ xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr
xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
lastUse = NULL, lastBaseUse = NULL;
xmlSchemaAttributePtr attrs;
int baseIsAnyType = 0;
int baseIsAnyType = 0;
/*
* Complex Type Definition with complex content Schema Component.
......@@ -5927,6 +6042,7 @@ xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr
}
if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) ||
(type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
/*
* Inherit the attribute uses of the base type.
*/
......@@ -5966,11 +6082,16 @@ xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr
attrs = type->subtypes->subtypes->attributes;
/*
* Handle attribute wildcards.
*/
type->attributeWildcard =
xmlSchemaBuildCompleteAttributeWildcard(ctxt,
attrs,
type->subtypes->subtypes->attributeWildcard);
*/
type->attributeWildcard = type->subtypes->subtypes->attributeWildcard;
if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
attrs, &type->attributeWildcard) == -1) {
if ((type->attributeWildcard != NULL) &&
(type->attributeWildcard != type->subtypes->subtypes->attributeWildcard))
type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
return (-1);
}
if ((type->attributeWildcard != NULL) &&
(type->attributeWildcard != type->subtypes->subtypes->attributeWildcard))
type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
......@@ -5992,6 +6113,65 @@ xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr
type->attributeWildcard = baseType->attributeWildcard;
}
}
if (!baseIsAnyType) {
if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
if (type->attributeWildcard != NULL) {
/*
* Derivation Valid (Restriction, Complex)
* 4.1 The {base type definition} must also have one.
*/
if (baseType->attributeWildcard == NULL) {
xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
"The derived type \"%s\" has an attribute wildcard, "
"but the base type \"%s\" does not have one.\n",
type->name, baseType->name);
return (1);
} else if (xmlSchemaIsWildcardNsConstraintSubset(ctxt,
type->attributeWildcard, baseType->attributeWildcard) == 0) {
/* 4.2 */
xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
"The wildcard in the derived type \"%s\" is not a valid "
"subset of the one in the base type \"%s\".\n",
type->name, baseType->name);
return (1);
}
/* 4.3 Unless the {base type definition} is the ur-type
* definition, the complex type definition's {attribute
* wildcard}'s {process contents} must be identical to or
* stronger than the {base type definition}'s {attribute
* wildcard}'s {process contents}, where strict is stronger
* than lax is stronger than skip.
*/
if (type->attributeWildcard->processContents <
baseType->attributeWildcard->processContents) {
xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
"The process contents of the wildcard in the "
"derived type \"%s\" is weaker than "
"that in the base type \"%s\".\n",
type->name, baseType->name);
return (1);
}
}
} else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
/*
* Derivation Valid (Extension)
* At this point the type and the base have both, either
* no wildcard or a wildcard.
*/
if ((baseType->attributeWildcard != NULL) &&
(baseType->attributeWildcard != type->attributeWildcard)) {
/* 1.3 */
if (xmlSchemaIsWildcardNsConstraintSubset(ctxt,
baseType->attributeWildcard, type->attributeWildcard) == 0) {
xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_COS_CT_EXTENDS_1_3,
"The wildcard in the derived type \"%s\" is not a valid "
"superset of the one in the base type \"%s\".\n",
type->name, baseType->name);
return (1);
}
}
}
}
} else {
/*
* Although the complexType is implicitely derived by "restriction"
......@@ -5999,9 +6179,18 @@ xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr
*/
baseType = NULL;
attrs = type->attributes;
if (attrs != NULL)
type->attributeWildcard =
xmlSchemaBuildCompleteAttributeWildcard(ctxt, attrs, type->attributeWildcard);
if (attrs != NULL) {
if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
attrs, &type->attributeWildcard) == -1) {
if ((type->attributeWildcard != NULL) &&
(type->attributeWildcard != type->subtypes->subtypes->attributeWildcard))
type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
return (-1);
}
if ((type->attributeWildcard != NULL) &&
((type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD) == 0))
type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
}
}
/*
* Gather attribute uses defined by this type.
......@@ -6089,6 +6278,7 @@ xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr
}
/*
* TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
* TODO: derivation-ok-restriction 2.1.3
*/
break;
}
......@@ -6152,13 +6342,13 @@ xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr
type->attributeUses = uses;
} else
lastBaseUse->next = uses;
}
}
} else {
/*
* Derive implicitely from the ur-type.
*/
* Derive implicitely from the ur-type.
*/
type->attributeUses = uses;
}