¿Cómo se manejan espacios de nombres arbitrarios al realizar consultas de Linq a XML?

Resuelto bouvard asked hace 15 años • 3 respuestas

Tengo un proyecto en el que estoy tomando un HTML "en vivo" particularmente feo y forzándolo a convertirlo en un DOM XML formal con HTML Agility Pack. Lo que me gustaría poder hacer es consultar 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 esto, no estoy seguro de cómo manejar los espacios de nombres. En un documento en particular, el HTML original en realidad tenía un formato XHTML deficiente con la siguiente etiqueta:

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

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

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

Aparentemente, para esas etiquetas "div" solo el nombre local es "div", pero el nombre de etiqueta adecuado es el espacio de nombres más "div". Intenté 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 complicada 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 que estoy consultando. ¿Alguien más ha tenido que hacer esto alguna vez? ¿Lo estoy haciendo demasiado complicado? Sé que podría evitar todo esto si me quedo con HtmlDocument y consulta con XPath, pero prefiero ceñirme a lo que sé (Linq) si es posible y también preferiría saber que no me estoy preparando para más espacios de nombres. cuestiones relacionadas en el futuro.

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

bouvard avatar Oct 08 '08 22:10 bouvard
Aceptado

Usarlo LocalNamedebería estar bien. No lo consideraría un truco en absoluto si no te importa en qué espacio de nombres se encuentra.

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 de 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 truco:

var x = namespaces.SelectMany(ns=>xDoc.Root.Descendants(ns+"div"));
Mark Cidade avatar Oct 08 '2008 15:10 Mark Cidade

Si sabe que el espacio de nombres 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");
StriplingWarrior avatar Aug 06 '2012 16:08 StriplingWarrior