.NET : How to validate XML file with DTD without DOCTYPE declaration
Asked Answered
W

3

9

I have an XML file with no DOCTYPE declaration that I would like to validate with an external DTD upon reading.

Dim x_set As Xml.XmlReaderSettings = New Xml.XmlReaderSettings()
x_set.XmlResolver = Nothing
x_set.CheckCharacters = False
x_set.ProhibitDtd = False
x = XmlTextReader.Create(sChemin, x_set)

How do you set the path for that external DTD? How do you validate?

Warthog answered 22/1, 2009 at 18:32 Comment(0)
R
16

I have used the following function successfully before, which should be easy to adapt. How ever this relies on creating a XmlDocument as magnifico mentioned. This can be achieved by:

XmlDocument doc = new XmlDocument();
doc.Load( filename );
doc.InsertBefore( doc.CreateDocumentType( "doc_type_name", null, DtdFilePath, null ), 
    doc.DocumentElement );


/// <summary>
/// Class to test a document against DTD
/// </summary>
/// <param name="doc">XML The document to validate</param>
private static bool ValidateDoc( XmlDocument doc )
{
    bool isXmlValid = true;
    StringBuilder xmlValMsg = new StringBuilder();

    StringWriter sw = new StringWriter();
    doc.Save( sw );
    doc.Save( TestFilename );

    XmlReaderSettings settings = new XmlReaderSettings();
    settings.ProhibitDtd = false;
    settings.ValidationType = ValidationType.DTD;
    settings.ValidationFlags = XmlSchemaValidationFlags.ReportValidationWarnings;
    settings.ValidationEventHandler += new ValidationEventHandler( delegate( object sender, ValidationEventArgs args )
    {
        isXmlValid = false;
        xmlValMsg.AppendLine( args.Message );
    } );

    XmlReader validator = XmlReader.Create( new StringReader( sw.ToString() ), settings );

    while( validator.Read() )
    {
    }
    validator.Close();

    string message = xmlValMsg.ToString();
    return isXmlValid;
}
Rentsch answered 25/2, 2009 at 7:25 Comment(4)
I'd vote this up 20 times if I could. I've gotten SOOO close but this did it. Thanks!Pilotage
Really useful answer. For those who read this, the most recent version of .NET framework prefers settings.DtdProcessing = DtdProcessing.Parse instead of settings.ProhibidDtd = false.Achondrite
So, the solution is still that we have to add the DOCTYPE string at the beginning? Is there a way for the code to point to an external location not specified in the DOCTYPE string?Lion
That "ProhibitDtd" is a nasty bomb that only MS could have invented. A more honest naming for this setting would have been LetsGetRidAllAllStandardComplianceSoAsToMakeYourLifeMiserable, which length and expressiveness is on par with .NET's style.Gird
A
1

Could you create an Xml.XmlDocument with the DTD you want, then append the XML file data to the in-memory Xml.XmlDocument, then validate that?

Approval answered 11/2, 2009 at 6:54 Comment(0)
P
-1
private static bool _isValid = true;
static void Main(string[] args)
{
    using (MemoryStream ms = new MemoryStream())
    {
        using (FileStream file = new FileStream("C:\\MyFolder\\Product.dtd", FileMode.Open, FileAccess.Read))
        {
            byte[] bytes = new byte[file.Length];
            file.Read(bytes, 0, (int) file.Length);
            ms.Write(bytes, 0, (int) file.Length);
        }
        using (FileStream file = new FileStream("C:\\MyFolder\\Product.xml", FileMode.Open, FileAccess.Read))
        {
            byte[] bytes = new byte[file.Length];
            file.Read(bytes, 0, (int) file.Length);
            ms.Write(bytes, 0, (int) file.Length);
        }
        ms.Position = 0;

        var settings = new XmlReaderSettings();
        settings.DtdProcessing = DtdProcessing.Parse;
        settings.ValidationType = ValidationType.DTD;
        settings.ValidationEventHandler += new ValidationEventHandler(OnValidationEvent);
        var reader = XmlReader.Create(ms, settings);

        // Parse the file.  
        while (reader.Read()) ;
    }
    // Check whether the document is valid or invalid.
    if (_isValid)
        Console.WriteLine("Document is valid");
    else
        Console.WriteLine("Document is invalid");
}

private static void OnValidationEvent(object obj, ValidationEventArgs args)
{
    _isValid = false;
    Console.WriteLine("Validation event\n" + args.Message);
}
Phenomenology answered 3/11, 2014 at 20:2 Comment(2)
Your answer should contain an explanation of your code and a description how it solves the problem.Hoashis
I could not find a way for xml to be validated against an external DTD document. In my case, I'm receiving XML from a tcp/ip socket and I want to validate this against a DTD file. The above example shows how you can combine a DTD and some XML together in the same stream before using the the XmlReader object to do the DTD validation.Phenomenology

© 2022 - 2024 — McMap. All rights reserved.