使用DTD验证XML文档

时间:2021-09-23 05:42:25

这本来应该不是一个困难的事情。但是,比较“无奈”的地方在于,必须在待验证的XML文档内部声明一个“DOCTYPE”引用DTD文件才可以验证。所以,更麻烦的问题在于需要为没有声明这个DOCTYPE的XML文档添加上这个声明。我还没有找到更好的办法。说明一下Context,需要执行此操作的是一个ASP.NET WebForm,XML文档来自于客户端上传的文件,而DTD文件位于服务器上。

下面说明一下具体的做法,虽然我最喜欢C#,但无奈于当前的Web项目必须使用VB.NET,因此这里的代码都是VB.NET。

首先,用XmlDocument对象加载客户端上传上来的XML文档流:

Dim  doc  As  XmlDocument  =   New  XmlDocument()
Try
    doc.Load(fu.FileContent)
Catch  ex  As  Exception
    errMsg.Text 
=  ex.Message
    
Return   False
    
Exit Function
End   Try

 

然后利用XmlDocument对象的InsertBefore对象插入需要的DOCTYPE:

doc.InsertBefore(doc.CreateDocumentType( " importfile " Nothing , MapPath( " dtdspec.dtd " ),  Nothing ), doc.DocumentElement)

 

 

将添加了DOCTYPE之后的XML文档保存到内存流中,并要记得把内存流的Position归零:

Dim  xmlStreamWithDTD  As  System.IO.MemoryStream
xmlStreamWithDTD 
=   New  System.IO.MemoryStream()
doc.Save(xmlStreamWithDTD)
xmlStreamWithDTD.Position 
=   0

 

最后利用XMLReader对象配合相应的设置,将内存流中的XML文档重新遍历一遍,进而得以验证XML文档是否符合DTD的定义:

 

Dim  settings  As  XmlReaderSettings  =   New  XmlReaderSettings()
settings.ProhibitDtd 
=   False
settings.ValidationType 
=  ValidationType.DTD
Dim  reader  As  XmlReader  =  XmlReader.Create(xmlStreamWithDTD, settings)
Try
    
While  reader.Read()
    
End   While
Catch  ex  As  Exception
    errMsg.Text 
=  ex.Message
End   Try

 

收工。 

 这么搞的问题在于内存要用两份,文档要遍历2遍,的确不是一个好办法,暂时只能这么样了,期待更好的做法。