使用 XSD 部分 XML 文件验证
Partial XML file validation using XSD
我正在尝试使用 XDocument class 和 XmlSchemaSet class 来验证 XMl 文件。
XML 文件已经存在,但我只想添加一个由几个其他元素组成的元素,我只想验证这个节点。
这里是 XML 文件的一个例子。我要验证的部分是 TestConfiguration
节点:
<?xml version="1.0" encoding="ISO-8859-1"?>
<Root>
<AppType>Test App</AppType>
<LabelMap>
<Label0>
<Title>Tests</Title>
<Indexes>1,2,3</Indexes>
</Label0>
</LabelMap>
<TestConfiguration>
<CalculateNumbers>true</CalculateNumbers>
<RoundToDecimalPoint>3</RoundToDecimalPoint>
</TestConfiguration>
</Root>
到目前为止,这是我的 xsd:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="TestConfiguration"
targetNamespace="MyApp_ConfigurationFiles" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="TestConfiguration">
<xs:complexType>
<xs:sequence>
<xs:element name="CalculateNumbers" type="xs:boolean" minOccurs="1" maxOccurs="1"/>
<xs:element name="RoundToDecimalPoint" type="xs:int" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
这是我用来验证它的代码:
private bool ValidateXML(string xmlFile, string xsdFile)
{
string xsdFilePath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) ?? string.Empty, xsdFile);
Logger.Info("Validating XML file against XSD schema file.");
Logger.Info("XML: " + xmlFile);
Logger.Info("XSD: " + xsdFilePath);
try
{
XDocument xsdDocument = XDocument.Load(xsdFilePath);
XmlSchemaSet schemaSet = new XmlSchemaSet();
schemaSet.Add(XmlSchema.Read(new StringReader(xsdDocument.ToString()), this.XmlValidationEventHandler));
XDocument xmlDocument = XDocument.Load(xmlFile);
xmlDocument.Validate(schemaSet, this.XmlValidationEventHandler);
}
catch (Exception e)
{
Logger.Info("Error parsing XML file: " + xmlFile);
throw new Exception(e.Message);
}
Logger.Info("XML validated against XSD.");
return true;
}
即使验证完整的 XML 文件,验证也会成功通过,导致我 运行 在尝试将 XML 文件加载到生成的 [=34= 中时遇到问题] 文件由 xsd2code 创建,错误:<Root xmlns=''> was not expected.
.
如何只验证 TestConfiguration
部分?
谢谢
你这里有几个问题:
验证整个文档在应该失败的时候成功了。
发生这种情况是因为模式不知道根节点,遇到未知节点被认为是验证警告而不是验证错误 - 即使那个未知节点是根元素。要在验证时启用警告,您需要设置 XmlSchemaValidationFlags.ReportValidationWarnings
. However, there's no way to pass this flag to XDocument.Validate()
. The question XDocument.Validate is always successful 显示了一种解决此问题的方法。
完成此操作后,您还必须在 ValidationEventArgs.Severity == XmlSeverityType.Warning
时在验证处理程序中抛出异常。
(至于在你的 XSD 中要求某个根元素,这显然是 not possible。)
您需要一种方便的方法来验证 元素 以及文档,这样您就可以验证您的 <TestConfiguration>
作品。
你的XSD和XML不一致。
您 XSD 指定您的元素在行 targetNamespace="MyApp_ConfigurationFiles" elementFormDefault="qualified"
中的 XML 命名空间 MyApp_ConfigurationFiles
中。事实上,您问题中显示的 XML 元素不在任何名称空间中。
如果 XSD 正确,您的 XML 根节点需要如下所示:
<Root xmlns="MyApp_ConfigurationFiles">
如果 XML 正确,您的 XSD 需要看起来像:
<xs:schema id="TestConfiguration"
elementFormDefault="unqualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
在解决了#3 中的 XSD 和 XML 不一致之后,您可以通过引入以下验证文档和元素的扩展方法来解决问题 #1 和 #2:
public static class XNodeExtensions
{
public static void Validate(this XContainer node, XmlReaderSettings settings)
{
if (node == null)
throw new ArgumentNullException();
using (var innerReader = node.CreateReader())
using (var reader = XmlReader.Create(innerReader, settings))
{
while (reader.Read())
;
}
}
public static void Validate(this XContainer node, XmlSchemaSet schemaSet, XmlSchemaValidationFlags validationFlags, ValidationEventHandler validationEventHandler)
{
var settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags |= validationFlags;
if (validationEventHandler != null)
settings.ValidationEventHandler += validationEventHandler;
settings.Schemas = schemaSet;
node.Validate(settings);
}
}
然后,要验证整个文档,请执行:
try
{
var xsdDocument = XDocument.Load(xsdFilePath);
var schemaSet = new XmlSchemaSet();
using (var xsdReader = xsdDocument.CreateReader())
schemaSet.Add(XmlSchema.Read(xsdReader, this.XmlSchemaEventHandler));
var xmlDocument = XDocument.Load(xmlFile);
xmlDocument.Validate(schemaSet, XmlSchemaValidationFlags.ReportValidationWarnings, XmlValidationEventHandler);
}
catch (Exception e)
{
Logger.Info("Error parsing XML file: " + xmlFile);
throw new Exception(e.Message);
}
要验证特定节点,您可以使用相同的扩展方法:
XNamespace elementNamespace = "MyApp_ConfigurationFiles";
var elementName = elementNamespace + "TestConfiguration";
try
{
var xsdDocument = XDocument.Load(xsdFilePath);
var schemaSet = new XmlSchemaSet();
using (var xsdReader = xsdDocument.CreateReader())
schemaSet.Add(XmlSchema.Read(xsdReader, this.XmlSchemaEventHandler));
var xmlDocument = XDocument.Load(xmlFile);
var element = xmlDocument.Root.Element(elementName);
element.Validate(schemaSet, XmlSchemaValidationFlags.ReportValidationWarnings, this.XmlValidationEventHandler);
}
catch (Exception e)
{
Logger.Info(string.Format("Error validating element {0} of XML file: {1}", elementName, xmlFile));
throw new Exception(e.Message);
}
现在验证整个文档失败,而验证 {MyApp_ConfigurationFiles}TestConfiguration
节点成功,使用以下验证事件处理程序:
void XmlSchemaEventHandler(object sender, ValidationEventArgs e)
{
if (e.Severity == XmlSeverityType.Error)
throw new XmlException(e.Message);
else if (e.Severity == XmlSeverityType.Warning)
Logger.Info(e.Message);
}
void XmlValidationEventHandler(object sender, ValidationEventArgs e)
{
if (e.Severity == XmlSeverityType.Error)
throw new XmlException(e.Message);
else if (e.Severity == XmlSeverityType.Warning)
throw new XmlException(e.Message);
}
我正在尝试使用 XDocument class 和 XmlSchemaSet class 来验证 XMl 文件。
XML 文件已经存在,但我只想添加一个由几个其他元素组成的元素,我只想验证这个节点。
这里是 XML 文件的一个例子。我要验证的部分是 TestConfiguration
节点:
<?xml version="1.0" encoding="ISO-8859-1"?>
<Root>
<AppType>Test App</AppType>
<LabelMap>
<Label0>
<Title>Tests</Title>
<Indexes>1,2,3</Indexes>
</Label0>
</LabelMap>
<TestConfiguration>
<CalculateNumbers>true</CalculateNumbers>
<RoundToDecimalPoint>3</RoundToDecimalPoint>
</TestConfiguration>
</Root>
到目前为止,这是我的 xsd:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="TestConfiguration"
targetNamespace="MyApp_ConfigurationFiles" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="TestConfiguration">
<xs:complexType>
<xs:sequence>
<xs:element name="CalculateNumbers" type="xs:boolean" minOccurs="1" maxOccurs="1"/>
<xs:element name="RoundToDecimalPoint" type="xs:int" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
这是我用来验证它的代码:
private bool ValidateXML(string xmlFile, string xsdFile)
{
string xsdFilePath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) ?? string.Empty, xsdFile);
Logger.Info("Validating XML file against XSD schema file.");
Logger.Info("XML: " + xmlFile);
Logger.Info("XSD: " + xsdFilePath);
try
{
XDocument xsdDocument = XDocument.Load(xsdFilePath);
XmlSchemaSet schemaSet = new XmlSchemaSet();
schemaSet.Add(XmlSchema.Read(new StringReader(xsdDocument.ToString()), this.XmlValidationEventHandler));
XDocument xmlDocument = XDocument.Load(xmlFile);
xmlDocument.Validate(schemaSet, this.XmlValidationEventHandler);
}
catch (Exception e)
{
Logger.Info("Error parsing XML file: " + xmlFile);
throw new Exception(e.Message);
}
Logger.Info("XML validated against XSD.");
return true;
}
即使验证完整的 XML 文件,验证也会成功通过,导致我 运行 在尝试将 XML 文件加载到生成的 [=34= 中时遇到问题] 文件由 xsd2code 创建,错误:<Root xmlns=''> was not expected.
.
如何只验证 TestConfiguration
部分?
谢谢
你这里有几个问题:
验证整个文档在应该失败的时候成功了。
发生这种情况是因为模式不知道根节点,遇到未知节点被认为是验证警告而不是验证错误 - 即使那个未知节点是根元素。要在验证时启用警告,您需要设置
XmlSchemaValidationFlags.ReportValidationWarnings
. However, there's no way to pass this flag toXDocument.Validate()
. The question XDocument.Validate is always successful 显示了一种解决此问题的方法。完成此操作后,您还必须在
ValidationEventArgs.Severity == XmlSeverityType.Warning
时在验证处理程序中抛出异常。(至于在你的 XSD 中要求某个根元素,这显然是 not possible。)
您需要一种方便的方法来验证 元素 以及文档,这样您就可以验证您的
<TestConfiguration>
作品。你的XSD和XML不一致。
您 XSD 指定您的元素在行
targetNamespace="MyApp_ConfigurationFiles" elementFormDefault="qualified"
中的 XML 命名空间MyApp_ConfigurationFiles
中。事实上,您问题中显示的 XML 元素不在任何名称空间中。如果 XSD 正确,您的 XML 根节点需要如下所示:
<Root xmlns="MyApp_ConfigurationFiles">
如果 XML 正确,您的 XSD 需要看起来像:
<xs:schema id="TestConfiguration" elementFormDefault="unqualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
在解决了#3 中的 XSD 和 XML 不一致之后,您可以通过引入以下验证文档和元素的扩展方法来解决问题 #1 和 #2:
public static class XNodeExtensions
{
public static void Validate(this XContainer node, XmlReaderSettings settings)
{
if (node == null)
throw new ArgumentNullException();
using (var innerReader = node.CreateReader())
using (var reader = XmlReader.Create(innerReader, settings))
{
while (reader.Read())
;
}
}
public static void Validate(this XContainer node, XmlSchemaSet schemaSet, XmlSchemaValidationFlags validationFlags, ValidationEventHandler validationEventHandler)
{
var settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags |= validationFlags;
if (validationEventHandler != null)
settings.ValidationEventHandler += validationEventHandler;
settings.Schemas = schemaSet;
node.Validate(settings);
}
}
然后,要验证整个文档,请执行:
try
{
var xsdDocument = XDocument.Load(xsdFilePath);
var schemaSet = new XmlSchemaSet();
using (var xsdReader = xsdDocument.CreateReader())
schemaSet.Add(XmlSchema.Read(xsdReader, this.XmlSchemaEventHandler));
var xmlDocument = XDocument.Load(xmlFile);
xmlDocument.Validate(schemaSet, XmlSchemaValidationFlags.ReportValidationWarnings, XmlValidationEventHandler);
}
catch (Exception e)
{
Logger.Info("Error parsing XML file: " + xmlFile);
throw new Exception(e.Message);
}
要验证特定节点,您可以使用相同的扩展方法:
XNamespace elementNamespace = "MyApp_ConfigurationFiles";
var elementName = elementNamespace + "TestConfiguration";
try
{
var xsdDocument = XDocument.Load(xsdFilePath);
var schemaSet = new XmlSchemaSet();
using (var xsdReader = xsdDocument.CreateReader())
schemaSet.Add(XmlSchema.Read(xsdReader, this.XmlSchemaEventHandler));
var xmlDocument = XDocument.Load(xmlFile);
var element = xmlDocument.Root.Element(elementName);
element.Validate(schemaSet, XmlSchemaValidationFlags.ReportValidationWarnings, this.XmlValidationEventHandler);
}
catch (Exception e)
{
Logger.Info(string.Format("Error validating element {0} of XML file: {1}", elementName, xmlFile));
throw new Exception(e.Message);
}
现在验证整个文档失败,而验证 {MyApp_ConfigurationFiles}TestConfiguration
节点成功,使用以下验证事件处理程序:
void XmlSchemaEventHandler(object sender, ValidationEventArgs e)
{
if (e.Severity == XmlSeverityType.Error)
throw new XmlException(e.Message);
else if (e.Severity == XmlSeverityType.Warning)
Logger.Info(e.Message);
}
void XmlValidationEventHandler(object sender, ValidationEventArgs e)
{
if (e.Severity == XmlSeverityType.Error)
throw new XmlException(e.Message);
else if (e.Severity == XmlSeverityType.Warning)
throw new XmlException(e.Message);
}