使用未定义的实体解析 XHTML 文档



在使用Python编码时,如果我必须加载带有未定义实体的XHTML文档,我会创建一个解析器并更新实体字典(即 nbsp ):

import xml.etree.ElementTree as ET
parser = ET.XMLParser()
parser.entity['nbsp'] = ' '
tree = ET.parse(opener.open(url), parser=parser)

VB.Net 我尝试将XHTML文档解析为Linq XDocument:

Dim x As XDocument = XDocument.Load(url)

这引发了 XmlException:

提及未申报的实体"nbsp"

谷歌搜索我

找不到任何如何更新实体表或使用简单方法来解析具有未定义实体的 XHTML 文档的示例。

如何解决这个看似简单的问题?

实体解析由底层解析器完成,该解析器在这里是一个标准XmlReader(或XmlTextReader)。

正式地,你应该在 DTD 中声明实体(参见 Oleg 的回答:XHTML 实体的问题),或者将 DTD 动态加载到文档中。这里有一些关于SO的例子,比如:加载到XDocument时如何解析实体?

您还可以创建一个 hacky XmlTextReader 派生类,该类在检测到实体时基于字典返回Text节点,就像我在下面的示例代码中演示的那样:

using (XmlTextReaderWithEntities reader = new XmlTextReaderWithEntities(MyXmlFile))
{
    reader.AddEntity("nbsp", "u00A0");
    XDocument xdoc = XDocument.Load(reader);
}
...
public class XmlTextReaderWithEntities : XmlTextReader
{
    private string _nextEntity;
    private Dictionary<string, string> _entities = new Dictionary<string, string>();
    // NOTE: override other constructors for completeness
    public XmlTextReaderWithEntities(string path)
        : base(path)
    {
    }
    public void AddEntity(string entity, string value)
    {
        _entities[entity] = value;
    }
    public override bool Read()
    {
        if (_nextEntity != null)
            return true;
        return base.Read();
    }
    public override XmlNodeType NodeType
    {
        get
        {
            if (_nextEntity != null)
                return XmlNodeType.Text;
            return base.NodeType;
        }
    }
    public override string Value
    {
        get
        {
            if (_nextEntity != null)
            {
                string value = _nextEntity;
                _nextEntity = null;
                return value;
            }
            return base.Value;
        }
    }
    public override void ResolveEntity()
    {
        // if not found, return the string as is
        if (!_entities.TryGetValue(LocalName, out _nextEntity))
        {
            _nextEntity = "&" + LocalName + ";";
        }
        // NOTE: we don't use base here. Depends on the scenario
    }
}

此方法适用于简单方案,但您可能需要重写其他一些内容以确保完整性。

PS:对不起,它是在C#中,你必须适应 VB.NET :)

我还没有这样做,但是您可以使用所需的实体声明创建一个XmlParserContext对象作为internalSubset。将该上下文传递给构造函数中的XmlTextReader,并通过加载读取器创建XDocument对象。在 MSDN 中,VB 中已经有一个简单的示例代码片段,用于使用预定义的实体。

在这种情况下,

我想你在网络上的一个页面,所以你可以使用可以满足你需求的HTML敏捷包。

我使用xpath,element和更多其他东西。搜索 html 页面等非常有用。

你可以在这里找到文档:htmlagilitypack

相关内容

  • 没有找到相关文章

最新更新