XDocument 不会解析 html 实体(例如 ),但 XmlDocument 会

Posted

技术标签:

【中文标题】XDocument 不会解析 html 实体(例如 ),但 XmlDocument 会【英文标题】:XDocument will not parse html entities (e.g. ) but XmlDocument will 【发布时间】:2014-05-22 07:12:06 【问题描述】:

我目前正在将在 XmlDocument 上运行的旧解析器转换为 XDocument。我这样做主要是为了获取 Linq 查询和添加的行号信息。

我的 xml 包含这样的元素:

<?xml version="1.0"?>
<fulltext>
    hello this is a failed textnode
    &#xC;
    and I don't know how to parse it.
</fulltext>

我的问题是,虽然 XmlDocument 读取该节点似乎没有问题:

var xmlDocument = new XmlDocument();

var physicalPath = GetPhysicalPath(uploadFolderFile);
try

    xmlDocument.Load(physicalPath);

catch (XmlException xmlException)

    _log.Warn("Problems with the document", xmlException);

上面的示例可以很好地解析文档,但是当我尝试这样做时:

XDocument xmlDocument;
var physicalPath = GetPhysicalPath(uploadFolderFile);
var xmlStream = new System.IO.StreamReader(physicalPath);
try

   xmlDocument = XDocument.Load(xmlStream, LoadOptions.SetLineInfo | LoadOptions.SetBaseUri);

catch (XmlException)

   _log.Warn("Trying to clean document for HexaDecimal", xmlException);

由于字符&amp;#xC;导致读取文件失败 XML 1.1 版中似乎允许使用特殊字符,但更改描述无济于事。 我考虑过只用 XmlDocument 解析文档然后转换它;但这似乎违反直觉。有人可以帮忙解决这个问题吗?

【问题讨论】:

【参考方案1】:

好的……所以我找到了解决这个问题的办法。

首先我尝试使用以下代码解析 xml:

private XDocument GetXmlDocument(String physicalPath)
    
        XDocument xmlDocument;
        var xmlStream = new System.IO.StreamReader(physicalPath);
        try
        
            xmlDocument = XDocument.Load(xmlStream, LoadOptions.SetLineInfo);
        
        catch (XmlException)
        
            //_log.Warn("Trying to clean document for HexaDecimal", xmlException);
            xmlDocument = XmlSanitizingStream.TryToCleanXMLBeforeParsing(physicalPath);
        

        return xmlDocument;
    

如果它无法加载文档,那么我将尝试使用这篇博文中使用的技术来清理它: http://seattlesoftware.wordpress.com/2008/09/11/hexadecimal-value-0-is-an-invalid-character/

它不会删除我之前提到的字符,但它会删除任何 XML 标准不允许的字符。

然后,在清理 XML 之后,我添加了一个 XMLReader 并将其设置设置为不检查字符:

public static XDocument TryToCleanXMLBeforeParsing(String physicalPath)

    string xml;

    Encoding encoding;
    using (var reader = new XmlSanitizingStream(File.OpenRead(physicalPath)))
    
        xml = reader.ReadToEnd();
        encoding = reader.CurrentEncoding;
    
    byte[] encodedString;
    if (encoding.Equals(Encoding.UTF8)) encodedString = Encoding.UTF8.GetBytes(xml);
    else if (encoding.Equals(Encoding.UTF32)) encodedString = Encoding.UTF32.GetBytes(xml);
    else encodedString = Encoding.Unicode.GetBytes(xml);

    var ms = new MemoryStream(encodedString);
    ms.Flush();
    ms.Position = 0;

    var settings = new XmlReaderSettings CheckCharacters = false;
    XmlReader xmlReader = XmlReader.Create(ms, settings);
    var xmlDocument = XDocument.Load(xmlReader);
    ms.Close();
    return xmlDocument;

由于在将忽略字符添加到阅读器之前,我已经清理了文档删除了非法字符,因此我很确定我没有阅读格式错误的 XML 文档。最坏的情况是我得到一个格式错误的 XML,无论如何它都会抛出一个错误。

我只用它来解析,它应该只用来读取数据。这不会使 XML 格式正确,并且在许多情况下会在代码的其他地方抛出异常。我之所以使用它,是因为我无法更改客户发送给我们的内容,我必须按原样阅读。

【讨论】:

以上是关于XDocument 不会解析 html 实体(例如 ),但 XmlDocument 会的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 中配置 XML 解析器以禁用外部实体解析

使用 Xdocument 进行简单的 Xml 解析

将 XElement 合并到 XDocument 并解析命名空间

无法使用 Xdocument 和 Linq 解析 xml 字符串

使用 C# 和 XDocument/XElement 解析 Soap 响应

我尝试使用 XDocument 解析 xml 文件中的文本,但并非所有结果都如我所愿,为啥?