How do I validate an XML document against a DTD in C#?
Asked Answered
L

4

7

I don't want to do anything fancy, I just want to make sure a document is valid, and print an error message if it is not. Google pointed me to this, but it seems XmlValidatingReader is obsolete (at least, that's what MonoDevelop tells me).

Edit: I'm trying Mehrdad's tip, but I'm having trouble. I think I've got most of it, but I can't find OnValidationEvent anywhere. Where go I get OnValidationEvent from?

XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.DTD;
settings.ValidationEventHandler += new ValidationEventHandler(/*trouble is here*/);
XmlReader validatingReader = XmlReader.Create(fileToLoad, settings);
Larine answered 1/11, 2009 at 21:7 Comment(2)
By the way, what do you mean by "converting to C#". My code is in C# 3.0.Transfigure
@Mehrdad: Sorry, I wrote that while I was still learning C# 1.0, and didn't know that var was valid in C#.Larine
T
7

Instead of creating XmlValidatingReader class directly, you should construct an appropriate XmlReaderSettings object and pass it as an argument to the XmlReader.Create method:

var settings = new XmlReaderSettings { ValidationType = ValidationType.DTD };
settings.ValidationEventHandler += new ValidationEventHandler(OnValidationEvent);
var reader = XmlReader.Create("file.xml", settings);

The rest is unchanged.

P.S. OnValidationEvent is the name of the method you declare to handle validation events. Obviously, you can remove the line if you don't want to subscribe to validation events raised by the XmlReader.

Transfigure answered 1/11, 2009 at 21:17 Comment(1)
Matthew: That's the method you'd declare to handle failed validation events. You can remove that line altogether if you want it to throw exception instead.Transfigure
S
3
var messages = new StringBuilder();
var settings = new XmlReaderSettings { ValidationType = ValidationType.DTD };
settings.ValidationEventHandler += (sender, args) => messages.AppendLine(args.Message);
var reader = XmlReader.Create("file.xml", settings);

if (messages.Length > 0)
{
    // Log Validation Errors
    // Throw Exception
    // Etc.
}

ValidationEventHandler

Lambda Expressions

Type Inference

Solangesolano answered 1/11, 2009 at 21:38 Comment(2)
Um, didn't Mehrdad give essentially the same answer, 22 minutes before you did?Kabuki
This answer is a different way of accomplishing the same thing.Solangesolano
R
0

I've referred to this example on DTD validation. https://learn.microsoft.com/en-us/dotnet/api/system.xml.xmlreadersettings.dtdprocessing?view=netcore-3.1#input

This example has invalid DTD XML, which I've corrected as below.

<!--XML file using a DTD-->
<!DOCTYPE store [
  <!ELEMENT store (item)*> 
  <!ELEMENT item (name,dept,price)>
  <!ATTLIST item type CDATA #REQUIRED ISBN CDATA 
#REQUIRED>
  <!ELEMENT name (#PCDATA)>
  <!ELEMENT dept (#PCDATA)>
  <!ELEMENT price (#PCDATA)>]>
<store>
  <item type="supplies"  ISBN="2-3631-4">
    <name>paint</name>
    <dept>1</dept>
    <price>16.95</price>
  </item>
</store>
Rammish answered 25/8, 2020 at 12:27 Comment(0)
M
-1

full description:

  1. In Visual Studio .NET, create a new Visual C# Console Application project named ValidateXml. Add two using statements to the beginning of Class1.cs as follows:

    using System.Xml;        // for XmlTextReader and XmlValidatingReader
    using System.Xml.Schema; // for XmlSchemaCollection (which is used later)
    
  2. In Class1.cs, declare a boolean variable named isValid before the start of the Main method as follows:

    private static bool isValid = true;      // If a validation error occurs,
                                             // set this flag to false in the
                                             // validation event handler. 
    
  3. Create an XmlTextReader object to read an XML document from a text file in the Main method, and then create an XmlValidatingReader to validate this XML data as follows:

    XmlTextReader r = new XmlTextReader("C:\\MyFolder\\ProductWithDTD.xml");
    XmlValidatingReader v = new XmlValidatingReader(r);
    
  4. The ValidationType property of the XmlValidatingReader object indicates the type of validation that is required (DTD, XDR, or Schema). Set this property to DTD as follows:

    v.ValidationType = ValidationType.DTD;
    
  5. If any validation errors occur, the validating reader generates a validation event. Add the following code to register a validation event handler (you will implement the MyValidationEventHandler method in Step 7):

    v.ValidationEventHandler += 
       new ValidationEventHandler(MyValidationEventHandler);
    
  6. Add the following code to read and validate the XML document. If any validation errors occur, MyValidationEventHandler is called to address the error. This method sets isValid to false (see Step 8). You can check the status of isValid after validation to see if the document is valid or invalid.

    while (v.Read())
    {
       // Can add code here to process the content.
    }
    v.Close();
    
    // Check whether the document is valid or invalid.
    if (isValid)
       Console.WriteLine("Document is valid");
    else
       Console.WriteLine("Document is invalid");
    
  7. Write the MyValidationEventHandler method after the Main method as follows:

    public static void MyValidationEventHandler(object sender, 
                                                ValidationEventArgs args) 
    {
       isValid = false;
       Console.WriteLine("Validation event\n" + args.Message);
    }
    

Build and run the application. The application should report that the XML document is valid. e.g.: In Visual Studio .NET, modify ProductWithDTD.xml to invalidate it (for example, delete the <AuthorName>M soliman</AuthorName> element). Run the application again. You should receive the following error message:

Validation event
Element 'Product' has invalid content. Expected 'ProductName'.
An error occurred at file:///C:/MyFolder/ProductWithDTD.xml(4, 5).
Document is invalid
Margarethe answered 26/5, 2013 at 8:53 Comment(1)
Meh - this is just a copy/paste of some MSDN sample, nearly verbatim. At the very least, provide a reference: support.microsoft.com/kb/307379Tontine

© 2022 - 2024 — McMap. All rights reserved.