Pregunta

Tengo un proyecto en el que estoy tomando algo particularmente feo "en vivo" HTML y forzarlo a un DOM XML formal con HTML Agility Pack. Lo que me gustaría poder hacer es consultar sobre esto con Linq to XML para poder extraer los bits que necesito. Estoy usando el método descrito aquí para analizar el HtmlDocument en un XDocument, pero cuando intento consultar sobre esto no estoy seguro de cómo manejar los espacios de nombres. En un documento en particular, el HTML original era XHTML mal formateado con la siguiente etiqueta:

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">

Cuando intento realizar una consulta desde este documento, parece que el atributo del espacio de nombres me impide hacer algo como:

var x = xDoc.Descendants("div");
// returns null

Aparentemente para aquellos "div" etiqueta solo el LocalName es " div " ;, pero el nombre de la etiqueta adecuada es el espacio de nombres más " div " ;. He intentado investigar un poco sobre el tema de los espacios de nombres XML y parece que puedo omitir el espacio de nombres consultando de esta manera:

var x = 
    (from x in xDoc.Descendants()
     where x.Name.LocalName == "div"
     select x);
// works

Sin embargo, esto parece una solución bastante hacky y no aborda adecuadamente el problema del espacio de nombres. Según tengo entendido, un documento XML adecuado puede contener múltiples espacios de nombres y, por lo tanto, la forma correcta de manejarlo debería ser analizar los espacios de nombres bajo los que estoy consultando. ¿Alguien más ha tenido que hacer esto? ¿Estoy haciendo que sea demasiado complicado? Sé que podría evitar todo esto simplemente manteniéndome con HtmlDocument y consultando con XPath, pero preferiría seguir con lo que sé (Linq) si es posible y también preferiría saber que no me estoy preparando para más espacio de nombres. problemas relacionados en el futuro.

¿Cuál es la forma correcta de manejar los espacios de nombres en esta situación?

¿Fue útil?

Solución

Usar LocalName debería estar bien. No lo consideraría un truco si no te importa en qué espacio de nombres está.

Si conoce el espacio de nombres que desea y desea especificarlo, puede:

var ns = "{http://www.w3.org/1999/xhtml}";
var x  = xDoc.Root.Descendants(ns + "div");

( referencia MSDN )

También puede obtener una lista de todos los espacios de nombres utilizados en el documento:

var namespaces = (from x in xDoc.Root.DescendantsAndSelf()
                  select x.Name.Namespace).Distinct();

Supongo que podrías usar eso para hacer esto, pero en realidad no es menos hack:

var x = namespaces.SelectMany(ns=>xDoc.Root.Descendants(ns+"div"));

Otros consejos

Si sabe que el espacio raíz será declarado por el elemento raíz del XML, como suele ser el caso, puede hacer esto:

var ns = xDoc.Root.Name.Namespace;
var x = xDoc.Descendants(ns + "div");
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top