- From: Jeni Tennison <jeni@jenitennison.com>
- Date: Sat, 23 Feb 2002 23:34:42 +0000
- To: "Paul Tomlinson" <ptomlinson@atmedicausa.com>
- CC: xmlschema-dev@w3.org
Hi Paul, > I'm encountering a rather unique error that may have to do with the actual > schema specification (verified with separate parsing engines) I'd like to > get someone else's eyes on. Take the following snippet of XML: > > --------- > <TopLevelElement > xmlns="http://someurl.com/namespace/data/1.0" > xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" > xsi:schemaLocation="http://someurl.com/namespace/data/1.0/thisForm.xsd"> > > <SecondLevelElement xmlns:Action="Add"> > ... > </SecondLevelElement> > </TopLevelElement> > --------- > > Note the "xmlns:" namespace qualifier in front of "Action", basically > declaring this attribute to exist in the currently defined space. I > *should* be able to take this off and simply have: > > <SecondLevelElement Action="Add"> Just to check that you're understanding what the xmlns: prefix actually does in the above. The attribute xmlns:Action="Add" attribute is a namespace declaration, that states that the prefix 'Action' is associated with the namespace 'Add' for the SecondLevelElement and all its descendants. It works in just the same way as all the other namespace declarations that you're using. Schema-aware processors won't report the xmlns:Action attribute as an attribute, because namespace declarations have a very specific purpose. This is *very* different from the attribute Action="Add" in your second example, which isn't a namespace declaration, but is a proper attribute. As with all attributes that lack prefixes, the Action attribute is in no namespace (this is the major way in which elements and attributes differ in terms of namespace-aware processing - the default namespace applies to elements that don't have prefixes, but doesn't apply to attributes without prefixes). Let's take a third example: <TopLevelElement xmlns="http://someurl.com/namespace/data/1.0" xmlns:ns="http://someurl.com/namespace/data/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://someurl.com/namespace/data/1.0 thisForm.xsd"> <SecondLevelElement ns:Action="Add"> ... </SecondLevelElement> </TopLevelElement> Here, the Action element has a 'ns' prefix, which is associated (through a namespace declaration on the TopLevelElement) with the namepsace http://someurl.com/namespace/data/1.0. This Action attribute is therefore in the http://someurl.com/namespace/data/1.0 namespace. > XMLSpy: This file is not valid: Unexpected attribute 'Action' - the parent > element requires some attributes to be qualified, because your Schema uses > attributeForm='qualified' or global attributes. You may need to specify a > prefix for your schema namespace. > > XMLSpy makes a great deal more sense, but still doesn't quite explain the > situation. The "Action" attribute *is* a global definition, but it's been > incorporated into the current namespace. Yes, that's what XMLSpy is saying. When you declare an attribute at the top level of the schema, you create a global declaration. Global declarations differ from local declarations in that *all* global declarations declare attributes as being in the target namespace of the schema. So when you do: > <xs:schema > xmlns="http://someurl.com/namespace/data/1.0" > xmlns:xs="http://www.w3.org/2001/XMLSchema" > targetNamespace="http://someurl.com/namespace/data/1.0" > elementFormDefault="qualified" > attributeFormDefault="unqualified"> > > <xs:attribute name="Action"> ... > </xs:attribute> > </xs:schema> you declare an Action attribute in the namespace http://someurl.com/namespace/data/1.0. Of the three earlier examples of the instance document, you'll recall that the only version in which the Action attribute was in the http://someurl.com/namespace/data/1.0 namespace was the third example, in which the Action attribute had a prefix that was associated with that namespace. When you refer to the attribute in the following: > <xs:schema > xmlns="http://someurl.com/namespace/data/1.0" > targetNamespace="http://someurl.com/namespace/data/1.0" > xmlns:xs="http://www.w3.org/2001/XMLSchema" > elementFormDefault="qualified" > attributeFormDefault="unqualified"> > > <xs:include schemaLocation="GenericTypes.xsd"/> > <xs:element name="TopLevelElement"> > <xs:complexType> > <xs:sequence> > ... > <xs:element name="SecondLevelElement" maxOccurs="unbounded"> > <xs:complexType> > <xs:complexContent> > <xs:extension base="SecondLevelType"> > <xs:attribute ref="Action"/> > </xs:extension> > </xs:complexContent> > </xs:complexType> > </xs:element> > ... > </xs:sequence> > </complexType> > </xs:element> > </xs:schema> The ref attribute holds a qualified name. This qualified name is interpreted relative to the default namespace declarations in force on the xs:attribute element. The default namespace at that point is the http://someurl.com/namespace/data/1.0 namespace. Therefore you're referring to the Action attribute in the http://someurl.com/namespace/data/1.0 namespace. So what you're saying is that the SecondLevelElement can have an attribute called Action in the http://someurl.com/namespace/data/1.0 namespace (and must not have any other attributes). XMLSpy gives you an error because it finds an Action attribute in no namespace. You haven't stated that the SecondLevelElement can have such an attribute, which is why it's a validity error. So you need to decide what you want -- do you want the Action attribute to be in the http://someurl.com/namespace/data/1.0 namespace or not? If you do, then you have to change the instance documents so that the http://someurl.com/namespace/data/1.0 namespace is declared with a namespace and the Action attribute is given that namespace wherever it's used. If you don't, you need to find a way of declaring the Action attribute *locally* so that it can remain "unqualified", which means that it isn't in the target namespace of the schema. The easiest way to do that (and still make the Action attribute reusable) is to declare it within an attribute group, as follows: <xs:schema xmlns="http://someurl.com/namespace/data/1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://someurl.com/namespace/data/1.0" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xs:attributeGroup name="ActionAttr"> <xs:attribute name="Action"> ... </xs:attribute> </xs:attributeGroup> </xs:schema> In this schema, the Action attribute is declared locally, within an attribute group. It doesn't have a form attribute of its own, and the attributeFormDefault of the schema is 'unqualified', so the Action attribute is declared as being in no namespace. In the schema that uses this GenericTypes.xsd schema, you can then pull in the Action attribute by referring to the ActionAttr attribute group as follows: <xs:schema xmlns="http://someurl.com/namespace/data/1.0" targetNamespace="http://someurl.com/namespace/data/1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xs:include schemaLocation="GenericTypes.xsd"/> <xs:element name="TopLevelElement"> <xs:complexType> <xs:sequence> ... <xs:element name="SecondLevelElement" maxOccurs="unbounded"> <xs:complexType> <xs:complexContent> <xs:extension base="SecondLevelType"> <xs:attributeGroup ref="ActionAttr"/> </xs:extension> </xs:complexContent> </xs:complexType> </xs:element> ... </xs:sequence> </complexType> </xs:element> </xs:schema> It's only a small change, but it makes all the difference in the world to the namespace in which the attribute is declared, and therefore whether or not you need to use a prefix when you use it or not. I should note that this revised schema in fact makes the third example (in which the attribute is given a prefix and therefore belongs to the http://someurl.com/namespace/data/1.0 namespace) invalid. I hope that clears things up, Jeni --- Jeni Tennison http://www.jenitennison.com/
Received on Saturday, 23 February 2002 18:34:45 UTC