FIX: The Validation of Keys Does Not Work If You Define More Than One Key (316797)



The information in this article applies to:

  • Microsoft XML Classes (included with the .NET Framework 1.0)

This article was previously published under Q316797

SYMPTOMS

If you define multiple keys in the XML Schema Definition (XSD) language schema file, as in the following example
<xsd:complexType name="JsmlDocumentType">
    <xsd:sequence>
	<xsd:element name="class" type="ClassType" minOccurs="1" maxOccurs="unbounded">
	  <xsd:key name="class-name-is-unique">
	    <xsd:selector xpath="class" />	
	    <xsd:field xpath="@name" />
	  </xsd:key>
	</xsd:element>
   </xsd:sequence>
</xsd:complexType>
		
<xsd:complexType name="ClassType" mixed="false">
   <xsd:sequence>
      <xsd:element name="events" type="EventsType" minOccurs="0" maxOccurs="1">
	<xsd:key name="event-name-is-unique">
	   <xsd:selector xpath="event" />
	   <xsd:field xpath="@name" />
	</xsd:key>
      </xsd:element>
...
</xsd:complexType>
				
you receive the following error message if you use the XmlValidatingReader class of the System.Xml namespace in .NET Framework to validate a XML file against the XSD file:
Exception Severity: Error
There is a duplicate key sequence 'InstanceCreated' for 'event-name-is-unique' key or unique identity constraint.

CAUSE

This problem occurs if the Identity Constraints on elements that are stored in the stack are not reset for later elements.

RESOLUTION

To work around this problem, move the element with the constraints so that it appears last.

STATUS

This bug was corrected in Microsoft .NET Framework Class Libraries 1.1.

MORE INFORMATION

Steps to Reproduce the Problem

  1. Create a new XML file named Test.xml, and then add the following code:
    <jsml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test.xsd">
    	
    	<class name="Singleton">
    		<events>
    			<event name="InstanceCreated" scope="class">
    				<desc>
    					Fired when the singleton instance is created.
    				</desc>
    			</event>
    		</events>
    		<property name="instance" scope="class" type="Singleton">
    			<desc>
    				Singleton instance, initialized on first access.
    			</desc>
    		</property>
    	</class>
    </jsml>
    					
  2. Save Test.xml to your computer's hard disk.
  3. Create a new .xsd file named Test.xsd, and then add the following code:
    <?xml version="1.0" encoding="utf-8" ?>
    <xsd:schema elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    	
    	<xsd:element name="jsml" type="JsmlDocumentType">
    		
    	</xsd:element>
    	
    	<xsd:complexType name="JsmlDocumentType">
    		<xsd:sequence>
    			<xsd:element name="class" type="ClassType" minOccurs="1" maxOccurs="unbounded">
    				<xsd:key name="class-name-is-unique">
    					<xsd:selector xpath="class" />
    					<xsd:field xpath="@name" />
    				</xsd:key>
    			</xsd:element>
    		</xsd:sequence>
    	</xsd:complexType>
    		
    	<xsd:complexType name="ClassType" mixed="false">
    		<xsd:sequence>
    			<xsd:element name="events" type="EventsType" minOccurs="0" maxOccurs="1">
    				<xsd:key name="event-name-is-unique">
    					<xsd:selector xpath="event" />
    					<xsd:field xpath="@name" />
    				</xsd:key>
    			</xsd:element>
    			<xsd:element name="property" type="PropertyType" minOccurs="0" maxOccurs="unbounded" />
    		</xsd:sequence>
    		<xsd:attribute name="name" type="xsd:string" use="required" />
    		<xsd:attribute name="inherits" type="xsd:string" use="optional" />
    	</xsd:complexType>
    	
    	
    	<xsd:complexType name="EventsType" mixed="false">
    		<xsd:sequence>
    			<xsd:element name="event" type="EventType" minOccurs="1" maxOccurs="unbounded" />
    		</xsd:sequence>
    	</xsd:complexType>
    	
    	<xsd:complexType name="EventType" mixed="false">
    		<xsd:sequence>
    			<xsd:element name="desc" type="DescriptionType" minOccurs="0" maxOccurs="1" />
    		</xsd:sequence>
    		<xsd:attribute name="name" type="xsd:string" use="required" />
    		<xsd:attribute name="scope" type="ScopeType" use="required" />
    	</xsd:complexType>
    	
    	<xsd:complexType name="PropertyType" mixed="false">
    		<xsd:sequence>
    			<xsd:element name="desc" type="xsd:string" minOccurs="0" maxOccurs="1" />
    		</xsd:sequence>
    		<xsd:attributeGroup ref="IdentifierAttributeGroup" />
    	</xsd:complexType>
    
    		
    	<xsd:attributeGroup name="IdentifierAttributeGroup">
    		<xsd:attribute name="name" type="xsd:string" use="required" />
    		<xsd:attribute name="scope" type="ScopeType" use="required" />
    		<xsd:attribute name="type" type="xsd:string" use="required" />
    	</xsd:attributeGroup>
    	
    	<xsd:simpleType name="DescriptionType">
    		<xsd:restriction base="xsd:string" />
    	</xsd:simpleType>
    	
    	<xsd:simpleType name="ScopeType">
    		<xsd:restriction base="xsd:string">
    			<xsd:enumeration value="class" />
    			<xsd:enumeration value="instance" />
    		</xsd:restriction>
    	</xsd:simpleType>
    	
    	<xsd:simpleType name="YesNoType">
    		<xsd:restriction base="xsd:string">
    			<xsd:enumeration value="yes" />
    			<xsd:enumeration value="no" />
    		</xsd:restriction>
    	</xsd:simpleType>
    </xsd:schema>
    
    					
  4. Save Test.xsd on drive C.
  5. Create a Microsoft Visual C# .NET console project, and then replace the code in Class1.cs with the following code:
    using System;
    using System.IO;
    using System.Xml;
    using System.Xml.Schema;
    
    namespace ConsoleApplication1
    {
    	/// <summary>
    	/// Summary description for Class1.
    	/// </summary>
    	class Class1
    	{
    		/// <summary>
    		/// The main entry point for the application.
    		/// </summary>
    		[STAThread]
    		static void Main(string[] args)
    		{
    			try
    			{
    				XmlTextReader tr = new XmlTextReader("c:\\test.xml");
    				XmlValidatingReader vr = new XmlValidatingReader(tr);
    				
    				vr.ValidationType = ValidationType.Schema;
    				vr.ValidationEventHandler += new ValidationEventHandler (ValidationHandler);
    
    				while(vr.Read());
    				
    				Console.Read();
    			}
    			catch(XmlException xmlEx)
    			{
    				Console.WriteLine(xmlEx.Message);
    				Console.WriteLine("line: " + xmlEx.LineNumber +"\n"+ "src: " + xmlEx.Source);
    				Console.WriteLine(xmlEx.ToString());
    			}
    			catch(Exception ex)
    			{
    				Console.WriteLine(ex.Message+ "\n" + ex.ToString());
    			}			
    		}
    		public static void ValidationHandler(object sender, ValidationEventArgs args)
    		{
    			Console.WriteLine("***Validation error");
    			Console.WriteLine("\tSeverity:{0}", args.Severity);
    			Console.WriteLine("\tMessage  :{0}", args.Message);
    			
    		}
    	}
    }
    
    					
  6. Compile the code, and then run it in debug mode:

    You receive the following error message:
    ***Validation error Severity:Error Message :There is a duplicate key sequence 'InstanceCreated' for 'event-name-is-unique' key or unique identity constraint. An error occurred at file:/ //c:/test.xml(5, 5).

Modification Type:MajorLast Reviewed:9/24/2003
Keywords:kbbug kbpending KB316797