我正在尝试使用XDocument类和XmlSchemaSet类来验证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文件加载到由xsd2code创建的生成的类文件中时,我会遇到问题,错误:<Root xmlns=''> was not expected.
。
如何仅验证TestConfiguration
件?
由于
答案 0 :(得分:1)
这里有一些问题:
验证整个文档失败时会成功。
这是因为架构未知根节点,并且遇到未知节点被视为验证警告而不是验证错误 - 即使该未知节点是根元素。要在验证时启用警告,您需要设置XmlSchemaValidationFlags.ReportValidationWarnings
。但是,没有办法将此标志传递给XDocument.Validate()
。问题XDocument.Validate is always successful显示了解决此问题的一种方法。
完成此操作后,您还必须在ValidationEventArgs.Severity == XmlSeverityType.Warning
时在验证处理程序中抛出异常。
(至于要求XSD中的某个根元素,这显然是not possible。)
您需要一种方便的方法来验证元素以及文档,这样您就可以验证<TestConfiguration>
件。
您的XSD和XML不一致。
您XSD指定您的元素位于行MyApp_ConfigurationFiles
中的XML名称空间targetNamespace="MyApp_ConfigurationFiles" elementFormDefault="qualified"
中。实际上,您问题中显示的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);
}