.NET:如何在没有DOCTYPE声明的情况下使用DTD验证XML文件

9

我有一个没有DOCTYPE声明的XML文件,我想在读取时使用外部DTD进行验证。

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)

如何设置外部DTD的路径?如何进行验证?

3个回答

16

我之前成功使用过以下函数,这个函数应该很容易适应。然而,这个函数依赖于创建一个XmlDocument,正如magnifico所提到的。可以通过以下方式实现:

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;
}

如果可以的话,我会投20次赞。我已经接近成功了,但是这个解决方案真的帮了我很多。谢谢! - CindyH
非常有用的回答。对于阅读此文的人来说,最新版本的.NET框架更喜欢使用settings.DtdProcessing = DtdProcessing.Parse而不是settings.ProhibidDtd = false。 - artragis
所以,解决方法仍然是在开头添加DOCTYPE字符串吗?代码有没有办法指向一个在DOCTYPE字符串中未指定的外部位置? - Harvey Lin
“ProhibitDtd”是只有微软才会发明的恶心设置。更诚实的命名应该是“让我们摆脱所有标准合规性,以使你的生活痛苦”,这种长度和表达与.NET的风格相当。 - Johan Boulé

1
你能否创建一个带有所需DTD的Xml.XmlDocument,然后将XML文件数据附加到内存中的Xml.XmlDocument,最后进行验证?

-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);
}

2
你的答案应该包含代码解释和描述它如何解决问题。 - AbcAeffchen
我找不到一种方法来使XML针对外部DTD文档进行验证。在我的情况下,我从tcp/ip套接字接收XML,并希望将其与DTD文件进行验证。上面的示例展示了如何将DTD和一些XML组合在同一个流中,然后使用XmlReader对象进行DTD验证。 - Matt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接