XSD - attribute restriction ignored when validating
I am having issues trying to test the below xsd against the below xml files. Are my tools bad, or is my xsd not functioning in a predictable way?
Software tested:
- xmllint (using libxml version 20707)
- XML Copy Editor 1.2.0.6
Expected results:
- test.xml validates
- test-bad.xml fails validation due to malformed account attribute in domain tag
Oberved results: - test.xml validates - test-bad.xml validates
test.xml
<?xml version="1.0" ?>
<!DOCTYPE configuration S开发者_C百科YSTEM "configuration.dtd">
<configuration timestamp="2011-03-23T20:16:57.222" version="2.2" xmlns="http://www.example.com/api/2.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com/api/2.2 configuration.xsd">
<domain account="4af17ss66f-c841-4b97-a94a-edd7a012176" >
</domain>
</configuration>
test-bad.xml
<?xml version="1.0" ?>
<!DOCTYPE configuration SYSTEM "configuration.dtd">
<configuration timestamp="2011-03-23T20:16:57.222" version="2.2" xmlns="http://www.example.com/api/2.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com/api/2.2 configuration.xsd">
<domain account="totally invalid account" >
</domain>
</configuration>
configuration.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.example.com/api/2.2" elementFormDefault="qualified" version="1.0" xml:lang="EN" targetNamespace="http://www.example.com/api/2.2">
<xs:element name="configuration">
<xs:complexType>
<xs:sequence>
<xs:element name="domain"/>
</xs:sequence>
<xs:attribute name="timestamp" type="xs:normalizedString" use="optional"/>
<xs:attribute name="version" type="xs:token" fixed="2.2"/>
</xs:complexType>
</xs:element>
<xs:element name="domain">
<xs:complexType>
<xs:sequence>
<xs:any minOccurs="0"/>
</xs:sequence>
<xs:attribute name="account" type="uid" use="required">
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:simpleType name="uid">
<xs:restriction base="xs:string">
<xs:length value="36"/>
<xs:pattern value="[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
configuration.dtd
<!ELEMENT configuration (domain)>
<!ATTLIST configuration
timestamp CDATA #IMPLIED
version CDATA #FIXED "2.2"
xmlns CDATA #IMPLIED
xmlns:xsi CDATA #IMPLIED
xsi:schemaLocation CDATA #IMPLIED>
<!ELEMENT domain ANY>
<!ATTLIST domain account CDATA #IMPLIED>
The problem is you've accidentally defined two different element
s with the name "domain".
This defines one, which can occur only inside configuration
:
<xs:element name="domain"/>
And this defines the other, which can only occur as a root element (you can see this if you remove the configuration
element and have domain
as the root - it won't validate anymore):
<xs:element name="domain">
<xs:complexType>
<xs:sequence>
<xs:any minOccurs="0"/>
</xs:sequence>
<xs:attribute name="account" type="uid" use="required">
</xs:attribute>
</xs:complexType>
</xs:element>
Since the first definition doesn't say anything about its attributes, in your sample document the attribute "account" on your domain
element is valid with any type.
To define only one element, the best way is to make the element
definition you have into a complexType
, and refer to that (the other alternative is to move all the complexType
stuff inside the first domain
deinfition):
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.example.com/api/2.2" elementFormDefault="qualified" version="1.0" xml:lang="EN" targetNamespace="http://www.example.com/api/2.2">
<xs:element name="configuration">
<xs:complexType>
<xs:sequence>
<xs:element name="domain" type="domain"/> <!-- changed here -->
</xs:sequence>
<xs:attribute name="timestamp" type="xs:normalizedString" use="optional"/>
<xs:attribute name="version" type="xs:token" fixed="2.2"/>
</xs:complexType>
</xs:element>
<xs:complexType name="domain"> <!-- and here -->
<xs:sequence>
<xs:any minOccurs="0"/>
</xs:sequence>
<xs:attribute name="account" type="uid" use="required">
</xs:attribute>
</xs:complexType>
<xs:simpleType name="uid">
<xs:restriction base="xs:string">
<xs:length value="36"/>
<xs:pattern value="[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
精彩评论