Xs: key, why validation check when the key value is not included in the key link?

I am interested in defining a key constraint in my Xsd. I understand that using xs:key should limit the value used for a member of a reference list of values.

Assuming we are using an Xsd sample,

 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="namespace1" xmlns:r="namespace1" elementFormDefault="qualified"> <xs:element name="root"> <xs:complexType> <xs:sequence> <xs:element name="A" type="r:A" maxOccurs="unbounded"> <xs:keyref name="dummy" refer="r:pNumKey"> <xs:selector xpath="part"/> <xs:field xpath="@ref-number"/> </xs:keyref> </xs:element> <xs:element name="B" type="r:B"/> </xs:sequence> </xs:complexType> <xs:key name="pNumKey"> <xs:selector xpath="r:B/r:part"/> <xs:field xpath="@key-number"/> </xs:key> </xs:element> <xs:complexType name="A"> <xs:sequence> <xs:element name="part" maxOccurs="unbounded"> <xs:complexType> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute name="ref-number" type="xs:integer"/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> <xs:complexType name="B"> <xs:sequence> <xs:element name="part" maxOccurs="unbounded"> <xs:complexType> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute name="key-number" type="xs:integer"/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:schema> 

Xml sample

 <root xmlns="namespace1"> <A> <!-- if the ref-number is not equal to one of the key-number, the validation will give error --> <part ref-number="1"/> </A> <A> <!-- if the ref-number is not equal to one of the key-number, the validation will give error --> <part ref-number="2"/> </A> <B> <part key-number="1"/> <part key-number="2"/> <part key-number="3"/> </B> </root> 

and let's say some simple check

 [TestMethod] public void Test_Schema() { string schemaFileName = @"sampleSchema.xsd"; string xmlFileName = @"sampleXml.xml"; XmlReaderSettings settings = new XmlReaderSettings { ValidationType = ValidationType.Schema, ValidationFlags = XmlSchemaValidationFlags.ProcessInlineSchema | XmlSchemaValidationFlags.ProcessSchemaLocation | XmlSchemaValidationFlags.ReportValidationWarnings, }; settings.Schemas.Add (schema); settings.ValidationEventHandler += (o, e) => { throw new Exception("CRASH"); }; XmlSchema schema = XmlSchema.Read ( File.OpenText (schemaFileName), (o, e) => { throw new Exception ("BOOM"); }); XmlReader reader = XmlReader.Create (xmlFileName, settings); while (reader.Read ()) { } } 

how to do this, check is still successful when i use bad values ​​for A/part[@ref-number] ?

 <root xmlns="namespace1"> <A> <!-- doesn't go CRASH BOOM bang! why not? :( --> <part ref-number="5"/> </A> <B> <part key-number="1"/> <part key-number="2"/> <part key-number="3"/> </B> </root> 

Is any one or all of the Xsd, Xml, or validation above incorrect? Or did I misunderstand the intended purpose of xs:key ?

+3
c # xsd xsd-validation
source share
2 answers

As usual, after a good night's rest and a fresh look, at least 2 errors were found in this exercise.

  • The first error checking identity restrictions is an explicit process called by XmlSchemaValidationFlags.ProcessIdentityConstraints set by XmlReaderSettings.ValidationFlag , and
  • the second error, msdn sample contains an error in the circuit, <xs:selector xpath="part"/> should read <xs:selector xpath="r:part"/> .

A full working sample is as follows:

 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="namespace1" xmlns:r="namespace1" elementFormDefault="qualified"> <xs:element name="root"> <xs:complexType> <xs:sequence> <xs:element name="A" type="r:A" maxOccurs="unbounded"> <xs:keyref name="dummy" refer="r:pNumKey"> <!-- without 'r:' below, key was not recognized, boo-urns msdn! --> <xs:selector xpath="r:part"/> <xs:field xpath="@ref-number"/> </xs:keyref> </xs:element> <xs:element name="B" type="r:B"/> </xs:sequence> </xs:complexType> <xs:key name="pNumKey"> <xs:selector xpath="r:B/r:part"/> <xs:field xpath="@key-number"/> </xs:key> </xs:element> <xs:complexType name="A"> <xs:sequence> <xs:element name="part" maxOccurs="unbounded"> <xs:complexType> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute name="ref-number" type="xs:integer"/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> <xs:complexType name="B"> <xs:sequence> <xs:element name="part" maxOccurs="unbounded"> <xs:complexType> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute name="key-number" type="xs:integer"/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:schema> 

Xml example

 <root xmlns="namespace1"> <A> <!-- goes CRASH BOOM bang! failure for the win! --> <part ref-number="5"/> </A> <B> <part key-number="1"/> <part key-number="2"/> <part key-number="3"/> </B> </root> 

simple validator

 [TestMethod] public void Test_Schema() { string schemaFileName = @"sampleSchema.xsd"; string xmlFileName = @"sampleXml.xml"; XmlSchema schema = XmlSchema.Read( File.OpenText(schemaFileName), (o, e) => { throw new Exception("BOOM"); }); XmlReaderSettings settings = new XmlReaderSettings { ValidationType = ValidationType.Schema, ValidationFlags = XmlSchemaValidationFlags.ProcessInlineSchema | XmlSchemaValidationFlags.ProcessSchemaLocation | XmlSchemaValidationFlags.ReportValidationWarnings | // d'oh! explicit flag for processing identity constraints! XmlSchemaValidationFlags.ProcessIdentityConstraints, }; settings.Schemas.Add(schema); settings.ValidationEventHandler += (o, e) => { throw new Exception("CRASH"); }; XmlReader reader = XmlReader.Create(xmlFileName, settings); while (reader.Read()) { } } 
+4
source share

I think you should use ValidationEventHandler:

 settings.ValidationEventHandler += new ValidationEventHandler (ValidationCallBack); private static void ValidationCallBack (object sender, ValidationEventArgs args) {} 
0
source share

All Articles