《XML入门》XSD示例在C#验证报错:bestellformular元素未声明
XML验证错误:未声明bestellformular元素的问题排查
问题描述
在C#程序中使用带验证的XmlReader加载bestellbeleg1.xml文件,通过schema.SourceUri = args[1]指定对应的XSD文件bestellbeleg1.xsd,执行XDocument.Load(reader)时出现以下验证错误:
Validation error: Das bestellformular-Element wurde nicht deklariert.
(翻译:验证错误:未声明bestellformular元素)
疑问:这是否是书中示例代码的错误?
注:自行编写的XML/XSD组合在该C#程序中仅触发验证警告。
书中示例代码
XML文件(bestellbeleg1.xml)
<?xml version="1.0" encoding="UTF-8"?> <bestellformular bestellnummer="01000" bestelldatum="2013-03-01" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="bestellbeleg1.xsd"> <kunde> <name>Hanna Maier</name> <strasse>Oststrasse 12</strasse> <plz>40678</plz> <ort>Düsseldorf</ort> </kunde> <positionen> <position artikelnr="0045"> <beschreibung>Rollo XBP 312</beschreibung> <gebinde>Stck</gebinde> <menge>5</menge> <europreis>50.00</europreis> </position> <position artikelnr="0023"> <beschreibung>Rollo MMX</beschreibung> <gebinde>Stck</gebinde> <menge>4</menge> <europreis>40.00</europreis> </position> </positionen> </bestellformular>
XSD文件(bestellbeleg1.xsd)
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:element name="bestellformular" type="formular"/> <xsd:complexType name="formular"> <xsd:sequence> <xsd:element name="kunde" type="kunde"/> <xsd:element name="positionen" type="positionen"/> </xsd:sequence> <xsd:attribute name="bestellnummer" type="xsd:short" use="required"/> <xsd:attribute name="bestelldatum" type="xsd:date" use="required"/> </xsd:complexType> <xsd:complexType name="kunde"> <xsd:sequence> <xsd:element name="name" type="xsd:string"/> <xsd:element name="strasse" type="xsd:string"/> <xsd:element name="plz" type="xsd:int"/> <xsd:element name="ort" type="xsd:string"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="positionen"> <xsd:sequence> <xsd:element name="position" minOccurs="0" maxOccurs="unbounded"> <xsd:complexType> <xsd:sequence> <xsd:element name="beschreibung" type="xsd:string"/> <xsd:element name="gebinde" type="gb"/> <xsd:element name="menge" type="xsd:decimal"/> <xsd:element name="europreis" type="xsd:decimal"/> </xsd:sequence> <xsd:attribute name="artikelnr" type="xsd:string" use="required"/> </xsd:complexType> </xsd:element> </xsd:sequence> </xsd:complexType> <xsd:simpleType name="gb"> <xsd:restriction base="xsd:string"> <xsd:enumeration value="Stck"/> <xsd:enumeration value="kg"/> <xsd:enumeration value="cm"/> </xsd:restriction> </xsd:simpleType> </xsd:schema>
问题结论
这不是书中示例的错误,问题出在C#程序的验证配置上。
原因分析
书中的XML和XSD均为无命名空间结构,而你的代码仅通过schema.SourceUri指定XSD路径,未正确将Schema关联到空命名空间的XmlSchemaSet中,导致XmlReader无法找到元素的定义,从而抛出“未声明元素”的错误。
你自定义的XML/XSD组合仅触发警告,说明该组合的Schema关联逻辑是正确的,警告属于非关键性验证问题(比如可选元素缺失等)。
修正后的C#验证代码
using System.Xml; using System.Xml.Schema; using System.Xml.Linq; class Program { static void Main(string[] args) { if (args.Length < 2) return; // 创建SchemaSet并添加XSD,关联空命名空间 XmlSchemaSet schemaSet = new XmlSchemaSet(); schemaSet.Add("", args[1]); XmlReaderSettings settings = new XmlReaderSettings(); settings.ValidationType = ValidationType.Schema; settings.Schemas = schemaSet; // 注册验证事件处理方法 settings.ValidationEventHandler += OnValidationEvent; using (XmlReader reader = XmlReader.Create(args[0], settings)) { XDocument.Load(reader); } } static void OnValidationEvent(object sender, ValidationEventArgs e) { Console.WriteLine($"{e.Severity}: {e.Message}"); } }
补充验证
如果直接使用支持自动加载XSD的工具(如Visual Studio的XML验证功能)打开书中的XML文件,会发现它可以正常通过验证,进一步说明示例代码本身是合法的。
内容的提问来源于stack exchange,提问作者user10316237
相关产品推荐
相关产品推荐

