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 elements 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>
加载中,请稍侯......
精彩评论