在C#中单次读取和验证XML与引用的XSD

时间:2012-03-21 14:12:37

标签: c# xml xsd xml-parsing xml-validation

我正在尝试从XML文件中读取数据,并根据它建议的XSD将其验证到单个数据结构(例如XmlDocument)中。我有一个解决方案,但它需要2次通过文件,我想知道是否有单程解决方案。

MyBooks.xml:

<Books xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
     xsi:noNamespaceSchemaLocation='books.xsd' id='999'>
    <Book>Book A</Book>
    <Book>Book B</Book>
</Books>

Books.xsd:

<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'
    elementFormDefault='qualified'
    attributeFormDefault='unqualified'>
    <xs:element name='Books'>
        <xs:complexType>
            <xs:sequence>
                <xs:element name='Book' type='xs:string' />
            </xs:sequence>
            <xs:attribute name='id' type='xs:unsignedShort' use='required' />
        </xs:complexType>
    </xs:element>
</xs:schema>

假设MyBooks.xml和Books.xsd位于同一目录中。

验证

//Given a filename pointing to the XML file
var settings = new XmlReaderSettings();

settings.ValidationType = ValidationType.Schema;

settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;

settings.CloseInput = true;
settings.ValidationEventHandler += new ValidationEventHandler(ValidationCB);
//eg:
//private static void ValidationCB(object sender, ValidationEventArgs args)
//{ throw new ApplicationException(args.Message); }

using(var reader = XmlReader.Create(filename, settings))
{ while(reader.Read()) ; }

读入XmlDocument:

XmlDocument x = new XmlDocument();
x.Load(filename);

当然,我可以收集节点,因为正在进行XmlReader的读取,但如果可能的话,我宁愿不必自己做。有什么建议吗?

提前致谢

1 个答案:

答案 0 :(得分:1)

你的解决方案非常接近;你需要做的是使用验证阅读器来加载你的XML;通过这种方式验证是通过一次通过你的加载完成的;验证错误不会阻止您加载文档。

这些是我通常与ValidateXml帮助函数一起使用的高级步骤;一切都从编译的XmlSchemaSet开始:

public bool ValidateXml(XmlSchemaSet xset)

我设置了阅读器设置(你也做过):

XmlReaderSettings settings = new XmlReaderSettings { ValidationType = ValidationType.Schema, Schemas = xset, ConformanceLevel = ConformanceLevel.Document };
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
// Use your helper class that collects validation events. 
XsdUtils.Utils.SmartValidationHandler svh = new XsdUtils.Utils.SmartValidationHandler(Paschi.Xml.DefaultResolver.Instance);
settings.ValidationEventHandler += svh.ValidationCallbackOne;

然后我找了一位读者:

XmlReader xvr = XmlReader.Create(filename, settings);

然后我读了文件,它带来了验证:

XmlDocument xdoc = new XmlDocument();
xdoc.Load(xvr);

您的验证处理程序现在有结果;我还做的一件事是确保加载的文档元素实际上在xml架构集中具有相应的全局元素定义。

XmlQualifiedName qn = XmlQualifiedName.Empty;
if (xdoc.DocumentElement != null)
{
        if (string.IsNullOrEmpty(xdoc.DocumentElement.NamespaceURI))
        {
              qn = new XmlQualifiedName(xdoc.DocumentElement.LocalName);
        }
        else
        {
               qn = new XmlQualifiedName(xdoc.DocumentElement.LocalName, xdoc.DocumentElement.NamespaceURI);
         }
}
return !(svh.HasError || qn.IsEmpty || (!xset.GlobalElements.Contains(qn)));