我可以使用架构 (XSD) 验证 XML,但它会在第一个错误/故障处停止,并且不会从那里继续。 有没有办法遍历整个 XML 文件?
至少我的猜测是阅读部分,但找不到另一个来做到这一点。
using (XmlReader reader = XmlReader.Create(xmlPath, settings))
{
while (reader.Read()) { }
}
完整代码
public class Program
{
private static List<string> errList = new();
static void ValidationEventHandler(object sender, ValidationEventArgs e)
{
if (e.Severity == XmlSeverityType.Warning)
{
errList.Add("WARNING: " + e.Message);
}
else if (e.Severity == XmlSeverityType.Error)
{
errList.Add("ERROR: " + e.Message);
}
}
static void Main(string[] args)
{
string xmlPath = @"path_here";
string schemePath = @"path_here";
XmlReaderSettings settings = new();
// Need this for resolving include and import
settings.Schemas.XmlResolver = new XmlUrlResolver();
// This might not be needed, I am using same settings to validate the input xml
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
settings.Schemas.Add("namespace_name_here", schemePath);
settings.ValidationEventHandler += ValidationEventHandler;
settings.Schemas.Compile();
// Create an XmlReader for the XML file
using (XmlReader reader = XmlReader.Create(xmlPath, settings))
{
while (reader.Read()) { }
}
if (errList.Any())
{
foreach (string msg in errList) { Console.WriteLine(msg); }
}
Console.ReadKey();
}
}
--- 编辑 ---
我正在使用一大组 XSD,并且在其他 XSD 中导入了右侧和左侧。 不同的命名空间中有 22 个 XSD =),但找不到将这些包含在此处的好方法吗? 这是 SFTI.se 上包含 XSD 的文件的链接。 https://sfti.se/download/18.3a0a1c2218723106f76484f0/1680520279996/Svefaktura1_Arkiv%202023-02-23.zip 文件内的 Zip:“XML-Schema for Svefaktura 1.0.zip”
文件夹“SvefakturaExempelfiler”中有 exmaple XML 文件
我将您的代码变成了一个最小但完整的示例,以通过简单的 XML 实例文档和简单的 XML 模式重现所谓的未能显示多个错误的情况:
using System;
using System.Xml;
using System.Xml.Schema;
using System.Collections.Generic;
using System.Linq;
using System.IO;
public class Program
{
private static List<string> errList = new();
static void ValidationEventHandler(object sender, ValidationEventArgs e)
{
if (e.Severity == XmlSeverityType.Warning)
{
errList.Add("WARNING: " + e.Message);
}
else if (e.Severity == XmlSeverityType.Error)
{
errList.Add("ERROR: " + e.Message);
}
}
static void Main(string[] args)
{
string xml = @"<root>
<item>a</item>
<item>1</item>
<item>b</item>
<item>2</item>
</root>";
string xsd = @"<xs:schema xmlns:xs=""http://www.w3.org/2001/XMLSchema"">
<xs:element name=""root"">
<xs:complexType>
<xs:sequence>
<xs:element name=""item"" type=""xs:decimal"" maxOccurs=""unbounded""/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>";
XmlReaderSettings settings = new();
// Need this for resolving include and import
settings.Schemas.XmlResolver = new XmlUrlResolver();
// This might not be needed, I am using same settings to validate the input xml
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
settings.Schemas.Add(null, XmlReader.Create(new StringReader(xsd)));
settings.ValidationEventHandler += ValidationEventHandler;
settings.Schemas.Compile();
// Create an XmlReader for the XML file
using (XmlReader reader = XmlReader.Create(new StringReader(xml), settings))
{
while (reader.Read()) { }
}
if (errList.Any())
{
foreach (string msg in errList) { Console.WriteLine(msg); }
}
Console.ReadKey();
}
}
输出:
ERROR: The 'item' element is invalid - The value 'a' is invalid according to its datatype 'http://www.w3.org/2001/XMLSchema:decimal' - The string 'a' is not a valid Decimal value.
ERROR: The 'item' element is invalid - The value 'b' is invalid according to its datatype 'http://www.w3.org/2001/XMLSchema:decimal' - The string 'b' is not a valid Decimal value.
因此发现并报告了这两个错误。
当然,与任何验证一样,如果您有一个完全错误的实例或元素,那么通常无法从仅声明第一个错误中恢复。
考虑显示一个 XML 和 XSD 示例,其中您的代码无法重现您期望的错误,以便我们判断是否可能。