【问题标题】:Partial XML file validation using XSD使用 XSD 验证部分 XML 文件
【发布时间】:2016-05-03 13:12:04
【问题描述】:

我正在尝试使用 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 创建的生成的类文件中时遇到问题,错误:&lt;Root xmlns=''&gt; was not expected.

如何仅验证 TestConfiguration 部分?

谢谢

【问题讨论】:

标签: c# xml validation xsd


【解决方案1】:

这里有几个问题:

  1. 验证整个文档成功时应该失败。

    发生这种情况是因为根节点对架构是未知的,遇到未知节点被视为验证警告而不是验证错误 - 即使该未知节点是根元素。要在验证时启用警告,您需要设置XmlSchemaValidationFlags.ReportValidationWarnings。但是,无法将此标志传递给XDocument.Validate()。问题XDocument.Validate is always successful 显示了解决此问题的一种方法。

    完成此操作后,您还必须在 ValidationEventArgs.Severity == XmlSeverityType.Warning 时在验证处理程序中抛出异常。

    (至于在 XSD 中需要某个根元素,这显然是 not possible。)

  2. 您需要一种方便的方法来验证 元素 以及文档,以便验证您的 &lt;TestConfiguration&gt; 部分。

  3. 您的 XSD 和 XML 不一致。

    您的 XSD 指定您的元素位于 XML 命名空间 MyApp_ConfigurationFiles 的行 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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-26
    • 2012-06-04
    • 2012-07-23
    • 2018-12-15
    • 1970-01-01
    • 2016-05-20
    相关资源
    最近更新 更多