防止解析XML时下载DTD

35

当使用XmlDocument.Load时,我发现如果文档引用了DTD,会建立到提供的URI的连接。有没有办法阻止这种情况发生?

5个回答

37

经过进一步的调查,也许你应该将XmlReaderSettings对象的XmlResolver属性设置为null。

'XmlResolver用于定位和打开XML实例文档,或者定位和打开XML实例文档引用的任何外部资源。这可能包括实体、DTD或模式。'

所以代码看起来像这样:

        XmlReaderSettings settings = new XmlReaderSettings();
        settings.XmlResolver = null;
        settings.DtdProcessing = DtdProcessing.Parse;
        XmlDocument doc = new XmlDocument();
        using (StringReader sr = new StringReader(xml))
            using (XmlReader reader = XmlReader.Create(sr, settings))
            {
                doc.Load(reader);
            }

6
还需要添加以下代码:settings.ProhibitDtd = false;否则就完美了。谢谢! - spender
3
这是一个有用的技巧,但请记住,它并不适用于所有的XML文档。如果文档实际上以某种方式引用了DTD(例如实体引用),那么在尝试读取文档时会出现XML异常。 - Peter Ruderman
2
我尝试了一下,也发现它确实可以工作,但是 MSDN 文档中的这条注释让我有些困扰:“如果设置为 null,在 XmlReader 尝试访问外部资源时将抛出 XmlException 异常”。显然这并没有发生,但有人知道为什么吗?有人愿意发表评论吗? - Steg
4
经过一些实验,我发现将“Processing”设置为“Parse”仍会去获取DTDs。这个方法对我很有用,让它不再傻乎乎的了:XmlReaderSettings settings = new XmlReaderSettings {DtdProcessing = DtdProcessing.Ignore}; - hoserdude

7

正在加载的文档有DTD。

使用:

settings.ProhibitDtd = true;

我看到以下异常:
服务无法启动。System.Xml.XmlException:由于安全原因,在此XML文档中禁止使用DTD。要启用DTD处理,请将XmlReaderSettings上的ProhibitDtd属性设置为false,并将设置传递给XmlReader.Create方法。
因此,在这种情况下,似乎必须将ProhibitDtd设置为true。
看起来ValidationType会解决问题,但是:
settings.ValidationType = ValidationType.None;

我仍然看到与DTD URI的连接。

5
这实际上是XML规范中的一个缺陷。W3C正在抱怨人们疯狂地访问服务器来加载模式数十亿次。不幸的是,几乎没有标准的XML库能够正确处理这个问题,它们一遍又一遍地访问服务器。
DTD的问题特别严重,因为DTD可能包含一般实体声明(例如& -> &),而XML文件可能实际上依赖于这些声明。因此,如果您的解析器选择放弃加载DTD,并且XML使用一般实体引用,则解析可能会失败。
唯一的解决方案是透明缓存实体解析器,将下载的文件放入某个存档文件中,在库搜索路径中自动创建该存档文件,并几乎自动捆绑到任何软件分发中。但即使在Java世界中也没有一个像样的EntityResolver,当然也没有内置于任何来自apache基金会的东西中。

3

尝试像这样:

XmlDocument doc = new XmlDocument();
using (StringReader sr = new StringReader(xml))
  using (XmlReader reader = XmlReader.Create(sr, new XmlReaderSettings()))
  {
     doc.Load(reader);
  }

这里需要注意的是,XmlReaderSettings默认将ProhibitDtd属性设置为true。

1
使用XMLReader加载文档,并将读取器设置的ValidationType属性设置为None

1
那不会对你有帮助,如果XML使用在DTD中定义的实体引用,因为这使得XML不是良好形式化的,而不是无效的。 - Robert Rossney
因此,我认为有必要处理DTD以正确处理实体引用。但在没有连接的情况下,这该怎么做呢? - spender
不行。如果您的文档中包含在DTD中定义的实体引用,则解析器需要该DTD。因此,您必须将DTD包含在要解析的XML中,或者将DTD缓存在本地。这就是我不喜欢使用实体引用的原因之一。 - Robert Rossney

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