我的问题有两个:当属性丢失时,确定行号以及该属性属于哪个元素。
我通过在 XDocument 创建中添加适当的选项来解决第一部分:
// create XDocument
var opts = LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo;
XDocument xDocument = XDocument.Parse(stringWriter.ToString(), opts);
现在我读入 XSD 并验证:
// Read in the XSD
string schema = File.ReadAllText("c:\myschema.xsd");
XmlSchemaSet xmlSchemaSet = new();
xmlSchemaSet.Add("http://www.company.com/Import/v1_9", XmlReader.Create(new StringReader(schema)));
// Validate the XML against the XSD
xDocument.Validate(xmlSchemaSet, (sender, ex) =>
{
string validationErr = string.Format($"XML Parse Error: Severity={ex.Severity} Line={ex.Exception.LineNumber} Position={ex.Exception.LinePosition}");
Debug.Print("validationErr: {0}", validationErr);
validationErr = string.Format($"Message={ex.Exception}");
Debug.Print("validationErr: {0}", validationErr);
}, true);
我的 XML 具有已知缺失的属性,会导致此输出进行调试:
validationErr: XML Parse Error: Severity=Error Line=436 Position=26
Message: System.Xml.Schema.XmlSchemaValidationException: The required attribute 'Desc' is missing.
这太棒了。我现在知道发生此错误的行和位置。除此之外,我想知道包含此错误的元素的完整路径。现在它只说属性“描述”丢失了。嗯,我可能有超过 15 个不同的元素类型具有该属性。这是我知道发生此错误的部分节点:
<Roads Count="1">
<Road Num="1" Width="168" Distance="19388" Unit="FT">
<Ident RecordId="" /> <<--- the Desc attribute goes here
<Notes />
</Road>
</Roads>
今天早上我一直在寻找一种打印类似内容的方法: The required attribute 'Desc' is Missing in Root 颂歌1 奥德2 ode3\道路\道路\标识。这比行号和位置更能帮助人们更好地查看它。尽管我们最终会同时使用两者,但完整路径会立即告诉我们在 SQL 数据库中的何处查找缺失值。那么有什么方法可以获取错误发生位置的更详细信息和路径吗?
你还没有说你是否准备使用不同的模式验证器来满足这个要求(事实上,你还没有说你正在使用哪个模式验证器,但我想我可以解决它)。
如果您使用 Saxon 模式验证器 [我公司的产品],则缺少属性的标准错误消息将如下所示:
Validation error on line 89 column 29 of books.xml:
FORG0001: Required attribute @Q{}DESC is missing on element <CATEGORY>
See https://www.w3.org/TR/xmlschema11-1/#cvc-complex-type clause 4
因此它会为您提供缺少属性的元素名称。
此外,如果您提供自己的
InvalidityHandler
,它将使用 Invalidity
对象进行调用,该对象包含一个 AbsolutePath
属性,给出发现无效的元素的路径(元素名称和位置)。在我的示例中,AbsolutePath
显示为
/Q{}BOOKLIST[1]/Q{}CATEGORIES[1]/Q{}CATEGORY[4]
尽管同样的信息也可以以其他格式提供。