Seleccionando el valor del atributo usando XPath y HtmlAgilityPack

c# html html-agility-pack xml xpath

Pregunta

Estoy tratando de obtener el segundo valor de atributo de una etiqueta meta usando una expresión xpath en el paquete de agilidad html: la etiqueta meta:

<meta name="pubdate" content="2012-08-30" />

La expresión de ruta xml que estoy usando:

//meta[@name='pubdate']/@content

Pero no devuelve nada. Intenté buscar e implementar esta solución:

//meta[@name='pubdate']/string(@content)

De otra manera:

string(//meta[@name='pubdate']/@content)

Pero le da una excepción xml en el paquete de agilidad html. Otra solución no funcionó tan bien.

//meta[@name='pubdate']/data(@content)

Por razones, quería usar solo la ruta xml (y no las funciones del paquete de agilidad html para obtener el valor del atributo). La función que uso está abajo:

date = TextfromOneNode(document.DocumentNode.SelectSingleNode(".//body"), "meta[@name='pubdate']/@content");
public static string TextfromOneNode(HtmlNode node, string xmlPath)
{
    string toReturn = "";
    if(node.SelectSingleNode(xmlPath) != null)
    {
        toReturn = node.SelectSingleNode(xmlPath).InnerText;
    }
    return toReturn;
}

Hasta ahora parece que no hay forma de usar la expresión de ruta XML para obtener un valor de atributo directamente. ¿Algunas ideas?

Respuesta aceptada

Hay una manera de usar HtmlNodeNavigator :

public static string TextfromOneNode(HtmlNode node, string xmlPath)
{
    string toReturn = "";
    var navigator = (HtmlAgilityPack.HtmlNodeNavigator)node.CreateNavigator();
    var result = navigator.SelectSingleNode(xmlPath);
    if(result != null)
    {
        toReturn = result.Value;
    }
    return toReturn;
}

El siguiente ejemplo de aplicación de consola muestra cómo HtmlNodeNavigator.SelectSingleNode() funciona con XPath que devuelve el elemento y XPath que devuelve el atributo:

var raw = @"<div>
<meta name='pubdate' content='2012-08-30' />
<span>foo</span>
</div>";
var doc = new HtmlAgilityPack.HtmlDocument(); 
doc.LoadHtml(raw);

var navigator = (HtmlAgilityPack.HtmlNodeNavigator)doc.CreateNavigator();

var xpath1 = "//meta[@name='pubdate']/@content";
var xpath2 = "//span";

var result = navigator.SelectSingleNode(xpath1);
Console.WriteLine(result.Value);
result = navigator.SelectSingleNode(xpath2);
Console.WriteLine(result.Value);

demo de dotnetfiddle

salida:

2012-08-30
foo

Respuesta popular

Usando xml linq

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string input = "<meta name=\"pubdate\" content=\"2012-08-30\" />";
            XElement meta = XElement.Parse(input);
            DateTime output = (DateTime)meta.Attribute("content");
        }
    }
}


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué