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, где мы можем контролировать происходящее) .
Я удалил некоторую избыточность и улучшил ваш асинхронный->синхронный мост (но я бы посоветовал вам удалить .Result
и использовать await
, т. е. возвращать Task<XmlDocument>
вместо XmlDocument
).
Надеюсь это поможет!
person
Florian Rappl
schedule
30.03.2018