Может ли Html Agility Pack предназначаться для элемента, основанного на атрибуте имени? - PullRequest
0 голосов
/ 31 января 2020

Используя Html Agility Pack , возможно ли нацелиться на указанное значение элемента c путем поиска его атрибута name вместо его позиции индекса в списке узлов? Например, как будет выбран элемент с name="description", если порядок элементов формы изменился, и проверить, существует ли он даже внутри формы?

Пример HTML:

<form>
    <input type="hidden" name="title" value="example">
    <input type="hidden" name="body" value="example">
    <input type="hidden" name="description" value="example">
    <input type="hidden" name="category" value="example">
    <input type="hidden" name="date" value="example">
</form

C# для элементов по номеру индекса. Это терпит неудачу, потому что не все HTML файлы имеют элементы формы в том же порядке, и иногда элементы ввода отсутствуют:

var doc = new HtmlDocument();
doc.Load(file);
var form = doc.DocumentNode.SelectSingleNode("//form");
var elements = form.SelectNodes("//input");

MyObject Obj = new MyObject();
Obj.Title = elements[0].Attributes["value"].Value;
Obj.Body = elements[1].Attributes["value"].Value;
Obj.Description = elements[2].Attributes["value"].Value;
Obj.Category = elements[3].Attributes["value"].Value;
Obj.Date = elements[4].Attributes["value"].Value;

1 Ответ

1 голос
/ 31 января 2020

Используя XPath в Html -Agility-Pack, вы можете искать практически все в документе html.

Используемая вами XPath просматривает весь form или список inputs, но вы не ищете конкретную c вещь.

Если вам нужно указать c Элемент, имеющий атрибут name, который содержит значение description, вы можете использовать следующий xpath для его поиска.

var doc = new HtmlDocument();
doc.Load(file);

var inputNode = doc.DocumentNode.SelectSingleNode("//input[@name='description']");

if (inputNode == null)
{
   Console.WriteLine("Empty Gift Box"); // nothing found.
}
else
{
   Console.WriteLine(inputNode.Attributes["value"].Value.ToString());
}
// Prints 'example'

// Or you can use a single line lookup and assignment.
// Note.. ?. means if the result was null / not found, set left side = null.
Obj.Title = doc.DocumentNode.SelectSingleNode("//input[@name='title']")?.Attributes["value"]?.Value.ToString();

Как это работает

// ищет весь документ
/ ищет тег сразу после тега перед ним (/ / форма / вход). Если бы между формой и вводом был другой тег, это дало бы 0 результатов.
.// ищет любой тег под указанным тегом c, для которого вы вызываете SelectNodes. если есть входные теги снаружи, они не будут захвачены в grandChild.

var parentNode = doc.DocumentNode.SelectNodes("//form");
var grandChild = parentNode.SelectNodes(".//input"); // must be part of form.

, если вы ищете определенный c индекс ввода, или атрибут, или значение, вы можете использовать поиск по ключевым словам ,

// Get any first node that has both name and value
var specificNode = doc.DocumentNode.SelectSingleNode("//input[@name and @value]");  

// Get first node that has specific name and value
var specificNode2 = doc.DocumentNode.SelectSingleNode("//input[@name='description' and @value='example']");

// Get 3rd input element
var thirdInput = doc.DocumentNode.SelectSingleNode("//input[3]");

Есть много других способов поиска в документе, но это должно привести вас в порядок. Обязательно прочитайте документацию HAP. и многие ответы уже доступны в StackOverflow в теге Html -Agility-Pack

Не забудьте пометьте пост, который отвечает на ваш пост как ответ.

...