XmlSchemaValidationException.LineNumber and LinePosition are 0 when validating an Xml Schema with XDocument.Validate
Asked Answered
R

3

7

I'm trying to validate an Xml fragment using an Xml Schema with the XDocument.Validate extension method. Whenever an invalid Xml fragment is used the ValidationEventHandler fires properly, however both the LineNumber and LinePosition properties of the XmlSchemaValidationException are 0.

private bool Validate(XDocument doc)
{
    bool isValid = true;
    List<string> validationErrors = new List<string>();

    XmlSchemaSet schemas = new XmlSchemaSet();
    schemas.Add(null, "MyCustomSchema.xsd");

    doc.Validate(schemas, (sender, args) =>
    {
        validationErrors.Add(String.Format("{0}: {1} [Ln {2} Col {3}]", 
            args.Severity, 
            args.Exception.Message, 
            args.Exception.LineNumber, 
            args.Exception.LinePosition));

        isValid = false;
    }, false);

    return isValid;
}

My goal in the above example is to use validationErrors for informing a user as to why the validation failed. When this method is used, however, the LineNumber and LinePosition are both 0.

The snippet seems simple enough and appears to work as expected in terms of validating against both valid and invalid Xml fragments.

Thanks in advance!

Rawdon answered 9/1, 2012 at 18:46 Comment(1)
As far as I can see the XmlSchemaValidator that gets instantiated only uses an internal DummyPostion and I don't see an option to get a better implementation injected.Durrett
N
6

You are not validating the textual representation of the Xml anymore but the object model. As a result there is no lines and positions because there is no file but XElement, XAttribute etc. objects in memory. Another helpful hint would be to ask yourself - what line and position should be returned if you modified (e.g. an elelment was added) the XDocument after it was loaded but before running validation? If you are not creating or modifying the Xml the fastest way would be to use XmlReader to validate your Xml document. As a bonus - if the input is a file or a stream - you should get line and position information in case of validation errors.

Nurse answered 24/1, 2012 at 23:1 Comment(2)
Pawel, thank you for your very reasonable response. I wanted to validate against the XDocument, since I already had a reference. I will change my app to validate against an XmlReader, and then create the XDocument reference when neeeded.Rawdon
I think you should be able to do both at the same time - you can set up the reader so that it validates the document and then pass the reader to the XDocument.Load() method...Nurse
A
1

In your ValidationEventHandler, sender implements the IXmlLineInfo interface, which contains members System.Xml.IXmlLineInfo.LineNumber and System.Xml.IXmlLineInfo.LinePosition

So you could do this:

doc.Validate(schemas, (sender, args) =>
{
    var lineInfo = sender as IXmlLineInfo;
    validationErrors.Add(String.Format("{0}: {1} [Ln {2} Col {3}]",
        args.Severity,
        args.Exception.Message,
        lineInfo?.LineNumber,
        lineInfo?.LinePosition));

    isValid = false;
}, false);
April answered 15/8, 2019 at 18:30 Comment(0)
I
0

It's an old question, but here is a way to preserve positions when creating an XDocument instance - make sure you use LoadOptions.SetLineInfo

XDocument.Parse(xml, LoadOptions.SetLineInfo);

Then you can extract position within Validate method.

Its answered 17/11, 2021 at 15:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.