如何解决XML验证中'Level属性未声明'及关联前缀错误
解决XML验证中的"The 'Level' attribute is not declared"及关联错误
执行XML验证时遇到矛盾问题:
- 保留XML中的
xmlns:xs="http://www.w3.org/2001/XMLSchema"命名空间,触发错误:The 'Level' attribute is not declared - 移除该命名空间,又触发错误:
The attribute 'type' has an invalid value 'xs:string' according to its schema type 'QName' - 'xs' is an undeclared prefix.
原XML文件
<Settings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:noNamespaceSchemaLocation="Settings.xsd"> <ItemId Level="Guest" xsi:type="xs:string">Tech Support</ItemId> <ItemType Level="Administrator" xsi:type="xs:int">1</ItemType> <ItemShift Level="User" xsi:type="xs:time">07:00:00</ItemShift> </Settings>
原XSD Schema文件
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" > <xs:simpleType name="typeLevels"> <xs:restriction base="xs:string"> <xs:enumeration value="Administrator" /> <xs:enumeration value="User" /> <xs:enumeration value="Guest" /> </xs:restriction> </xs:simpleType> <xs:attribute name="Level" type="typeLevels" /> <xs:complexType name="MySettings"> <xs:sequence> <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded" /> </xs:sequence> <xs:anyAttribute namespace="##targetNamespace" processContents="lax"/> </xs:complexType> <xs:element name="Settings" type="MySettings"/> </xs:schema>
验证用C#代码
void Validate(string xml, string xsd) { var schemaSet = new XmlSchemaSet(); schemaSet.Add(null, xsd); var settings = new XmlReaderSettings { ValidationType = ValidationType.Schema }; settings.Schemas = schemaSet; settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation | XmlSchemaValidationFlags.ProcessInlineSchema; settings.ValidationEventHandler += (sender, e) => { switch (e.Severity){ case XmlSeverityType.Error: Console.WriteLine(e.Message); break; }}; using (XmlReader validator = XmlReader.Create(xml, settings)) { while (validator.Read()) ; } }
彻底解决方案
问题根源
原XSD中xs:anyAttribute指定了namespace="##targetNamespace",仅允许属于XSD目标命名空间(此处为无命名空间)的属性,但XML中声明xmlns:xs后,解析器无法正确关联全局定义的Level属性;同时移除xs命名空间会导致xsi:type中的xs前缀未声明。
修改XSD文件
将xs:anyAttribute的namespace改为##any,允许所有命名空间的属性(包括无命名空间的Level和xsi命名空间的属性),修改后的XSD如下:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" > <xs:simpleType name="typeLevels"> <xs:restriction base="xs:string"> <xs:enumeration value="Administrator" /> <xs:enumeration value="User" /> <xs:enumeration value="Guest" /> </xs:restriction> </xs:simpleType> <xs:attribute name="Level" type="typeLevels" /> <xs:complexType name="MySettings"> <xs:sequence> <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded" /> </xs:sequence> <!-- 修改namespace为##any,允许所有命名空间的属性 --> <xs:anyAttribute namespace="##any" processContents="lax"/> </xs:complexType> <xs:element name="Settings" type="MySettings"/> </xs:schema>
验证效果
- 保留XML中的
xmlns:xs和xmlns:xsi命名空间,无需修改XML Level属性会被XSD中全局定义的typeLevels类型验证xsi:type中的xs:string等前缀因xmlns:xs声明可被正确识别- C#验证代码无需修改,执行后无错误输出
内容的提问来源于stack exchange,提问作者volody
相关产品推荐
相关产品推荐

