2009-10-02 22 views
5

我正在測試以驗證XML文件。我使用這個代碼問題驗證在C中使用本地DTD文件的XML文件

XmlReaderSettings settings = new XmlReaderSettings(); 
settings.ProhibitDtd = false; 
settings.ValidationType = ValidationType.DTD; 

settings.ValidationEventHandler += new ValidationEventHandler(validationError);   

XmlSchemaSet schemas = new XmlSchemaSet(); 
settings.Schemas = schemas; 
XmlReader reader = XmlReader.Create(lblXmlPath.Text, settings); 

reader.Settings.Schemas.Add(null, lblDTDPath.Text); 
while (reader.Read()) 
{ 
      // empty by now 
} 
reader.Close(); 

但在該行 「reader.Settings.Schemas.Add(NULL,lblDTDPath.Text);」 Visual Studio中告訴我的錯誤「出於安全原因的DTD此XML文檔中禁止的。爲了使DTD處理設置ProhibitDtd屬性上XmlReaderSettings爲false,並通過設置成XmlReader.Create法」

正如你可以看到的代碼,ProhibitDtd設置爲false(我也在調試過程中驗證過)。我還嘗試在調用XmlReader.Create()之前添加Schema,但沒有成功。

回答

0

從我周圍的唯一辦法可以得到它的工作不是將模式添加到XmlReader。在xml文檔中指定的DTD必須是有效的url,並且XmlReader將每次都下載它。

如果您需要的瑪是本地的,你可以改變DTD的URL中使用正則表達式指向一個本地文件,所以它看起來財產以後像

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.3//EN" "file:C:\wml.dtd"> 

注意文件:在網址中。在將它傳遞給XmlReader之前,在內存中執行此操作,這樣,您不必修改xml文件即可將其改爲正確。

+0

,但我希望用戶從HD中選擇兩個文件,XML和dtd,並告訴他XML是否有效。我很確定它可以完成,但我不知道如何:( – Jonathan 2009-10-02 11:43:33

+0

更新我的aswer與一個可能的解決方案從本地文件加載DTD – Geoff 2009-10-02 12:12:32

0

嘗試在調用XmlReader.Create之前將DTD模式添加到模式集合中。

XmlReaderSettings settings = new XmlReaderSettings(); 
settings.ProhibitDtd = false; 
settings.ValidationType = ValidationType.DTD; 

settings.ValidationEventHandler += new ValidationEventHandler(validationError);   

XmlSchemaSet schemas = new XmlSchemaSet(); 

schemas.Add(null, lblDTDPath.Text); 
settings.Schemas = schemas; 

XmlReader reader = XmlReader.Create(lblXmlPath.Text, settings); 

while (reader.Read()) 
{ 
      // empty by now 
} 
reader.Close(); 
+0

我也試過紅外之前(現在再次)沒有我得到了同樣的錯誤,這有點令人沮喪xD – Jonathan 2009-10-02 12:00:07

+0

@Johnathan也許,在創建XmlReader(在上面的原始示例中)之後,檢查** XmlReader.Settings.ProhibitDtd **的值,看看它是否真的是false ?從你的問題,我不確定這是你檢查的價值,還是初始設置的價值.ProhibitDtd。只要確保它們顯示相同的值。如果讀者沒有,嘗試將其設置爲在加載你的模式之前假嗎?你可能已經嘗試過了,但是沒有其他東西看起來像它可能是一個問題? – 2009-10-02 12:48:42

+1

@Jonathan:你真的設法讓這個工作與一個.dtd文件嗎?我不' t認爲XmlSchemaSet可以與.dtd一起使用文件...只有.xsd文件。無論我嘗試什麼,我都會收到錯誤消息。 – fretje 2010-06-16 14:33:22

0

我有一個類似的問題。對我來說,答案是DTD不需要通過Schema連接,因爲XML文件指出了,通過模式添加導致了我的問題。

+0

我會盡快嘗試。謝謝。 – Jonathan 2009-11-03 20:10:56

2

我在驗證RSS提要前做了一段時間。通過本地存儲的DTD做驗證的方法是插入自定義XmlResolverXmlReader

XmlReaderSettings readerSettings = new XmlReaderSettings(); 
readerSettings.ValidationType = ValidationType.DTD; 
readerSettings.ProhibitDtd = false; 
readerSettings.XmlResolver = new XmlFakeDtdResolver(); 

這將使讀者在本地DTD(已知格式),而不是從DOCTYPE給出的網址下載。

class XmlFakeDtdResolver : XmlUrlResolver 
{ 
    public static Dictionary<Uri, byte[]> dtdMap = new Dictionary<Uri, byte[]>(); 
    public static Dictionary<string, Uri> uriMap = new Dictionary<string, Uri>(); 
    static XmlFakeDtdResolver() 
    { 
     Uri rss091uri = new Uri("http://fake.uri/rss091"); 
     uriMap["-//Netscape Communications//DTD RSS 0.91//EN"] = rss091uri; 
     uriMap["http://my.netscape.com/publish/formats/rss-0.91.dtd"] = rss091uri; 
     dtdMap[rss091uri] = Encoding.ASCII.GetBytes(Resources.rss_0_91dtd); 
    } 

    public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn) 
    { 
     if (dtdMap.ContainsKey(absoluteUri) && ofObjectToReturn == typeof(Stream)) 
     { 
      return new MemoryStream(dtdMap[absoluteUri]); 
     } 
     return base.GetEntity(absoluteUri, role, ofObjectToReturn); 
    } 

    public override Uri ResolveUri(Uri baseUri, string relativeUri) 
    { 
     if (uriMap.ContainsKey(relativeUri)) 
      return uriMap[relativeUri]; 
     return base.ResolveUri(baseUri, relativeUri); 
    } 
} 

作爲最終音符,我決定到底要不要使用DTD驗證,並通過XML模式去驗證,其中一個原因是許多飼料不包括DOCTYPE