Окружите существующий узел другим узлом с помощью Agility Pack

Как бы вы окружили все таблицы узлом <div class="overflow"></div>? По-видимому, этого не происходит:

if (oldElement.Name == "table")
{
    HtmlDocument doc = new HtmlDocument();
    HtmlNode newElement = doc.CreateElement("div");
    newElement.SetAttributeValue("class", "overflow");
    newElement.AppendChild(oldElement);
    oldElement.ParentNode.ReplaceChild(newElement, oldElement);
}

Когда я пробую этот код, с таблицами ничего не происходит. Но если я использую:

if (oldElement.Name == "table")
{
    oldElement.Remove();
}

Все таблицы действительно удалены, поэтому я уверен, что получаю доступ к правильным узлам.


person Christer William Persson    schedule 18.07.2012    source источник


Ответы (2)


Это может быть немного некрасиво, но вы можете просто отредактировать атрибут InnerHtml узла oldElement.ParentNode следующим образом:

if (oldElement.Name == "table")
{
    oldElement.ParentNode.InnerHtml = "\r\n<div class=\"overflow\">\r\n"
        + oldElement.OuterHtml +
        "\r\n</div>\r\n";
}

Также не похоже, что вы могли бы редактировать атрибут OuterHtml oldElement (поэтому сначала вам нужно получить ParentNode). HtmlAgilityPack говорит, что вы можете получить / установить OuterHtml, но VS2010 сообщал мне, что это свойство только для чтения.

Изменить

Я поигрался с кодом, чтобы понять это, и увидел, что oldElement.ParentNode становится узлом <div> после вызова AppendChild(). Решение, которое я нашел, состоит в том, чтобы сделать еще один HtmlNode в начале блока if для хранения родительского элемента, а затем вызвать ReplaceChild() на этом узле в конце:

if (oldElement.Name == "table")
{
    HtmlNode theParent = oldElement.ParentNode;

    HtmlDocument doc = new HtmlDocument();
    HtmlNode newElement = doc.CreateElement("div");
    newElement.SetAttributeValue("class", "overflow");
    newElement.AppendChild(oldElement);

    theParent.ReplaceChild(newElement, oldElement);
}
person Ichabod Clay    schedule 18.07.2012
comment
Ах, вот в чем проблема. На самом деле я не мог понять, почему код ничего не делал. Но ваше решение сработало как шарм :) - person Christer William Persson; 18.07.2012

Взгляните на CsQuery, порт jQuery на C #. Это легко сделать. Сначала загрузите документ:

CQ doc = CQ.CreateFromFile(..)  // or
CQ doc = CQ.CreateFromUrl(..)   // or
CQ doc = CQ.Create(string)

Создайте структуру для обертывания, вот четыре разных способа сделать это.

var wrap = CQ.CreateFragment("<div class='overflow'></div>");   // or

// you can pass HTML as a selector as in jQuery. The property indexer for a CQ
// object is the default method, same as $(..)

var wrap = doc["<div class='overflow'></div>"];   // or

var wrap = doc["<div />"].AddClass("overflow");  // or

// creates an element directly, sames as browser DOM methods

var wrap = doc.Document.CreateElement("div");
wrap.ClassName="overflow";

Оберните все таблицы структурой:

doc["table"].Wrap(wrap);          // or use longhand for the Select method

doc.Select("table").Wrap(wrap);   

Преобразуйте весь документ в строку:

string html = doc.Render();
person Jamie Treworgy    schedule 18.07.2012
comment
Вау, я обязательно буду использовать это для будущих проектов, похоже, вы создали что-то действительно прочное :) Но я боюсь, что не смогу реализовать это в моем текущем проекте, так как у меня немного не хватает времени на данный момент, и я не хочу смешивать парсеры. - person Christer William Persson; 18.07.2012
comment
На то, чтобы начать работу, потребовалось немного времени, но сейчас есть ядро ​​активных пользователей, и, похоже, они завоевывают популярность! Рад, что тебе тоже интересно. - person Jamie Treworgy; 18.07.2012