【问题标题】:AngleSharp parsing to valid HTML <script> and XMLAngleSharp 解析为有效的 HTML <script> 和 XML
【发布时间】:2018-03-28 15:20:50
【问题描述】:

我正在使用 AngleSharp 为网站编写解析器,我最终需要获取 XML。

在xml中解析的时候,解析段脚本有问题,因为有""这样的符号。 编号的行出现错误

我该如何解决这种情况(我需要使用 AngleSharp)?我尝试了不同的网站,结果是一样的

        var config = Configuration.Default
                      .WithCss()
                      .WithDefaultLoader();
        var address = Url.Create("https://www.google.com/");
        var document = BrowsingContext.New(config).OpenAsync(address).GetAwaiter().GetResult();

        XmlDocument xmlDocument = new XmlDocument();
        var xDocument = new HtmlParser().Parse(document.DocumentElement.InnerHtml);
        var formatter = new AngleSharp.Xml.XmlMarkupFormatter();
        var result = xDocument.ToHtml(formatter);
        xmlDocument.LoadXml(result); //1

        var parserXML = new XmlParser().Parse(document.DocumentElement.InnerHtml);//2
        xmlDocument.LoadXml(parserXML.ToHtml());

【问题讨论】:

    标签: anglesharp


    【解决方案1】:

    XML 与 HTML 不兼容,尽管它们非常相似。因此,通常这是不可能的,但是,当您定义如何处理差异时,您可能会得出可接受的结果。

    在这种转换的核心,需要定义以下函数。我们只处理 4 种节点类型 - 不应该出现其他任何类型。为简单起见,我们丢弃任何命名空间的元素或属性。

    static XmlNode CreateNodeFrom(XmlDocument document, INode source)
    {
        switch (source.NodeType)
        {
            case NodeType.Comment:
                return document.CreateComment(source.TextContent);
            case NodeType.Element:
                var original = (IElement)source;
                var element = document.CreateElement(original.LocalName);
    
                foreach (var attr in original.Attributes)
                {
                    element.SetAttribute(attr.Name, attr.Value);
                }
    
                return element;
            case NodeType.Text:
                return document.CreateTextNode(source.TextContent);
            default:
                return null;
        }
    }
    

    该功能将几乎完全从树形转换器中使用:

    static void AppendChildren(INode source, XmlNode target)
    {
        var owner = target.OwnerDocument;
    
        foreach (var child in source.ChildNodes)
        {
            var node = CreateNodeFrom(owner, child);
            target.AppendChild(node);
            AppendChildren(child, node);
        }
    }
    

    所以我们只是遍历树并转换我们所看到的...更改您的原始功能:

    var config = Configuration.Default.WithCss().WithDefaultLoader();
    var address = Url.Create("https://www.google.com/");
    var document = BrowsingContext.New(config).OpenAsync(address).Result;
    var xmlDocument = new XmlDocument();
    var root = CreateNodeFrom(xmlDocument, document.DocumentElement);
    xmlDocument.AppendChild(root);
    AppendChildren(document.DocumentElement, root);
    

    (我不知道你为什么使用所有这些不同的解析器;解析器在文本级别工作,但 HTML 和 XML 在文本级别不兼容 - 所以让我们尝试在 DOM 级别进行转换,这是我们可以控制什么的地方正在发生)。

    我删除了一些冗余并改进了您的 async->sync 桥(但我鼓励您删除 .Result 并使用 await,即返回 Task&lt;XmlDocument&gt; 而不是 XmlDocument)。

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 2016-07-05
      • 1970-01-01
      • 2017-10-16
      • 2014-04-15
      • 2018-12-30
      • 2020-03-31
      • 2015-10-20
      • 2018-06-14
      • 1970-01-01
      相关资源
      最近更新 更多