在previous question中我提到过一些使用第三方 DLL 的工作,其接口(interface)使用一系列使用 DTD 定义的 XML 输入。到目前为止,一切都很顺利,但在解决生成的输入值中的文档类型声明时,我仍然遇到这个棘手的问题。
我不明白的是决定在哪里查找引用的 DTD 文件的决定因素是什么。如果我有一个如下所示的声明:
<!DOCTYPE ElementName SYSTEM "ElementName.dtd">
我最初的想法是应用程序的当前执行路径是解析器查找 DTD 的位置。但是,当我尝试使用XML control时在 ASP.Net 中,我遇到的错误让我困惑......
Could not find file 'c:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ElementName.dtd'
为什么要在那里寻找 DTD?
有没有 XML 专家可以帮助我解决这个问题。我确实无法控制从此 DLL 返回的 XML,所以我应该做什么。有没有办法向操作系统“注册”DTD?喜欢 GAC 吗?
最佳答案
不幸的是,生成 XML 的库使用 dtd 的相对 URL,而不是完全限定的 URL。因此,XmlControl 的 XmlDocument 使用 XmlResolver类将相对路径转换为完全限定路径。默认情况下它使用 XmlUrlResolver (这是一个具体的 XmlResolver)。这将尝试将 dtd 的位置映射到它认为相对于 Xml 文档的位置。问题是,XmlDocument 在哪里?可能在与任何内容无关的内存中,并且 XmlUrlResolver 正在使用进程位置,而在您的情况下,它是位于“c:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe”的 Visual Studio。
那么你能做什么呢?好吧,我想您必须创建自己的 XmlResolver,它继承自 XmlUrlResolver,并覆盖 ResolveUri 方法并执行适当的操作。完成此操作后,您必须:
- 创建一个 XmlReaderSettings 类并将 XmlReolver 属性设置为您刚刚创建的类。
- 使用传入文档和 XmlSettings 对象的 XmlReader.Create() 创建 XmlReader。
- 创建一个 XmlDocument 并调用 Load,最后传入 XmlReader。
- 将 XmlControl 的 XmlDocument 属性设置为 XmlDocument。
坦率地说,这有点麻烦,所以如果是我的话,我只会使用 string.Replace 从文档中删除 DTD 声明,然后再将其处理为 XML。
如果您真的很勇敢,您可以创建一个直接继承自 XmlResolver 的解析器。完成后,您可以覆盖 GetEntity方法,然后你可以从任何你喜欢的地方获取 dtd 文档。我曾经写过一个从作为资源文件嵌入的文件中获取 dtds 的代码,但不幸的是,我不再有代码了:-(
关于asp.net - DOCTYPE 解析和 ASP.Net 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/703858/