XDocument内联模式。SchemaInfo为空

时间:2022-04-28 17:17:47

OK, so here we go. I've got a set of XML documents that I'm loading into my app. In my little test I've created a reader that validates against the schema specified by the XML document. Using the following code it works quite nicely.

好,我们开始。我在应用程序中加载了一组XML文档。使用下面的代码,它工作得非常好。

// Set the validation settings.
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);

// Create the XmlReader object.
XmlReader reader = XmlReader.Create("xml/note.xml", settings);

// Load the XDocument from the reader
XDocument loadedDoc = XDocument.Load(reader);

Now my XML document gets loaded correctly and any validation errors that occur are handled by the callback.

现在,我的XML文档被正确地加载,任何发生的验证错误都由回调处理。

However, if I want to get schema information about an element by calling GetSchemaInfo() on said element, I'm given null. This question here talks about using an overloaded Validate method, but that doesn't really apply to this situation, unless I'm missing something.

但是,如果我想通过调用上述元素上的GetSchemaInfo()来获取关于元素的模式信息,就会得到null。这里的问题是关于使用重载的Validate方法,但是这并不适用于这种情况,除非我漏掉了什么。

Is it possible to get the schema info loaded into the XDoc using an inline schema or should I be doing this another way?

是否可以使用内联模式将模式信息加载到XDoc中,或者我是否应该以另一种方式执行?

1 个解决方案

#1


0  

Check out my answer to my own question.

看看我对自己问题的回答。

The first paragraph after the code block is what is important to you, but basically, the SchemaInfo will be there, but it is not added until after the validation callback.

代码块后面的第一段对您来说很重要,但是基本上,SchemaInfo会在那里,但是在验证回调之后才会添加它。

The workaround I used was basically this (NOTE: this code was tested and works when loading an XML directly and calling XDocument.Validate on an XmlSchemaSet, but the premise should be the same or similar with XmlReader and inline schemas):

我使用的解决方案基本上是这样的(注意:当直接加载XML并调用XDocument时,测试并运行此代码。在XmlSchemaSet上进行验证,但是前提应该与XmlReader和内联模式相同或相似):

List<XElement> errorElements = new List<XElement>();

serializedObject.Validate((sender, args) =>
{
    var exception = (args.Exception as XmlSchemaValidationException);

    if (exception != null)
    {
        var element = (exception.SourceObject as XElement);

        if (element != null)
            errorElements.Add(element);
     }

});

foreach element in errorElements
{
    var si = element.GetSchemaInfo; 

    // do something with SchemaInfo
}

I was only trying to capture SchemaInfo for elements, hence the as cast and null check, but this should work for other node types like Attributes (not tested though, so i could be wrong).

我只是试图为元素捕获SchemaInfo,因此使用了as cast和null检查,但是这应该适用于其他节点类型,比如属性(虽然没有经过测试,所以可能是错误的)。

If you are looking to use a specific callback method instead of an anonymous delegate, your errorElements will need to be a class level field and you can do what you need to do with it after the validation is complete (again, I will add in the untested tag).

如果您希望使用一个特定的回调方法而不是匿名委托,那么您的errorElements将需要是一个类级字段,您可以在验证完成后对其进行所需的操作(同样,我将添加未测试的标记)。

public class SomeClass
{

    List<XElement> errorElements = new List<XElement>();

    public void Load()
    {

        // Set the validation settings.
        XmlReaderSettings settings = new XmlReaderSettings();
        settings.ValidationType = ValidationType.Schema;
        settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
        settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
        settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
        settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
        settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);

        // Create the XmlReader object.
        XmlReader reader = XmlReader.Create("xml/note.xml", settings);

        // Load the XDocument from the reader
        XDocument loadedDoc = XDocument.Load(reader);

        // do something with errorElements

    }

    public void ValidationCallBack(object sender, ValidationEventArgs e)
    {
        var exception = (args.Exception as XmlSchemaValidationException);

        if (exception != null)
        {
            var element = (exception.SourceObject as XElement);

            if (element != null)
                errorElements.Add(element);
         }

    }

}

In response to your comment about wanting the IXSchemaInfo for all nodes, the Schema info is added to the XElement after the validation regardless of whether the node failed or passed, so your requirement would actually be easier since you do not need to keep a list of failed nodes. You should be able to do this:

为了响应您关于希望IXSchemaInfo用于所有节点的评论,验证之后将模式信息添加到XElement中,而不考虑节点是否失败或通过,因此您的需求实际上会更容易,因为您不需要保存失败节点的列表。你应该能够做到:

public void Load()
{

    // Set the validation settings.
    XmlReaderSettings settings = new XmlReaderSettings();
    settings.ValidationType = ValidationType.Schema;
    settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
    settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
    settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
    settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
    settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);

    // Create the XmlReader object.
    XmlReader reader = XmlReader.Create("xml/note.xml", settings);

    // Load the XDocument from the reader
    XDocument loadedDoc = XDocument.Load(reader);

    foreach (var node in loadedDoc.Descendants())
    {
        var si = node.GetSchemaInfo();
    }

}

The above example will only access the XElements in your XDocument but it is just to illustrate my point. Once the loading is complete and the xml is validate, the schema info should be there.

上面的示例只访问XDocument中的xelement,但它只是为了说明我的观点。一旦加载完成并验证了xml,模式信息就应该在那里。

#1


0  

Check out my answer to my own question.

看看我对自己问题的回答。

The first paragraph after the code block is what is important to you, but basically, the SchemaInfo will be there, but it is not added until after the validation callback.

代码块后面的第一段对您来说很重要,但是基本上,SchemaInfo会在那里,但是在验证回调之后才会添加它。

The workaround I used was basically this (NOTE: this code was tested and works when loading an XML directly and calling XDocument.Validate on an XmlSchemaSet, but the premise should be the same or similar with XmlReader and inline schemas):

我使用的解决方案基本上是这样的(注意:当直接加载XML并调用XDocument时,测试并运行此代码。在XmlSchemaSet上进行验证,但是前提应该与XmlReader和内联模式相同或相似):

List<XElement> errorElements = new List<XElement>();

serializedObject.Validate((sender, args) =>
{
    var exception = (args.Exception as XmlSchemaValidationException);

    if (exception != null)
    {
        var element = (exception.SourceObject as XElement);

        if (element != null)
            errorElements.Add(element);
     }

});

foreach element in errorElements
{
    var si = element.GetSchemaInfo; 

    // do something with SchemaInfo
}

I was only trying to capture SchemaInfo for elements, hence the as cast and null check, but this should work for other node types like Attributes (not tested though, so i could be wrong).

我只是试图为元素捕获SchemaInfo,因此使用了as cast和null检查,但是这应该适用于其他节点类型,比如属性(虽然没有经过测试,所以可能是错误的)。

If you are looking to use a specific callback method instead of an anonymous delegate, your errorElements will need to be a class level field and you can do what you need to do with it after the validation is complete (again, I will add in the untested tag).

如果您希望使用一个特定的回调方法而不是匿名委托,那么您的errorElements将需要是一个类级字段,您可以在验证完成后对其进行所需的操作(同样,我将添加未测试的标记)。

public class SomeClass
{

    List<XElement> errorElements = new List<XElement>();

    public void Load()
    {

        // Set the validation settings.
        XmlReaderSettings settings = new XmlReaderSettings();
        settings.ValidationType = ValidationType.Schema;
        settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
        settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
        settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
        settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
        settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);

        // Create the XmlReader object.
        XmlReader reader = XmlReader.Create("xml/note.xml", settings);

        // Load the XDocument from the reader
        XDocument loadedDoc = XDocument.Load(reader);

        // do something with errorElements

    }

    public void ValidationCallBack(object sender, ValidationEventArgs e)
    {
        var exception = (args.Exception as XmlSchemaValidationException);

        if (exception != null)
        {
            var element = (exception.SourceObject as XElement);

            if (element != null)
                errorElements.Add(element);
         }

    }

}

In response to your comment about wanting the IXSchemaInfo for all nodes, the Schema info is added to the XElement after the validation regardless of whether the node failed or passed, so your requirement would actually be easier since you do not need to keep a list of failed nodes. You should be able to do this:

为了响应您关于希望IXSchemaInfo用于所有节点的评论,验证之后将模式信息添加到XElement中,而不考虑节点是否失败或通过,因此您的需求实际上会更容易,因为您不需要保存失败节点的列表。你应该能够做到:

public void Load()
{

    // Set the validation settings.
    XmlReaderSettings settings = new XmlReaderSettings();
    settings.ValidationType = ValidationType.Schema;
    settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
    settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
    settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
    settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
    settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);

    // Create the XmlReader object.
    XmlReader reader = XmlReader.Create("xml/note.xml", settings);

    // Load the XDocument from the reader
    XDocument loadedDoc = XDocument.Load(reader);

    foreach (var node in loadedDoc.Descendants())
    {
        var si = node.GetSchemaInfo();
    }

}

The above example will only access the XElements in your XDocument but it is just to illustrate my point. Once the loading is complete and the xml is validate, the schema info should be there.

上面的示例只访问XDocument中的xelement,但它只是为了说明我的观点。一旦加载完成并验证了xml,模式信息就应该在那里。