Domanda

Ho un progetto in cui prendo alcuni "brutti" particolarmente brutti HTML e forzandolo in un DOM XML formale con HTML Agility Pack. Quello che vorrei poter fare è quindi interrogare su questo con Linq to XML in modo da poter cancellare i bit di cui ho bisogno. Sto usando il metodo descritto qui per analizzare l'HtmlDocument in un XDocument, ma quando provo a interrogarlo non sono sicuro di come gestire gli spazi dei nomi. In un particolare documento l'HTML originale era in realtà XHTML mal formattato con il seguente tag:

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

Quando provo a interrogare da questo documento sembra che l'attributo namespace mi impedisca di fare qualcosa del tipo:

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

Apparentemente per quelli "div" tag solo il LocalName è "div", ma il nome del tag corretto è lo spazio dei nomi più "div". Ho provato a fare qualche ricerca sul problema degli spazi dei nomi XML e sembra che posso bypassare lo spazio dei nomi eseguendo una query in questo modo:

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

Tuttavia, questa sembra una soluzione piuttosto confusa e non risolve correttamente il problema dello spazio dei nomi. A quanto ho capito, un documento XML adeguato può contenere più spazi dei nomi e quindi il modo corretto di gestirlo dovrebbe essere quello di analizzare gli spazi dei nomi in cui sto interrogando. Qualcun altro ha mai dovuto farlo? Sto solo diventando complicato? So che potrei evitare tutto ciò semplicemente attaccando HtmlDocument e interrogando con XPath, ma preferirei attenermi a ciò che so (Linq) se possibile e preferirei anche sapere che non mi sto preparando per ulteriori spazi dei nomi- problemi correlati lungo la strada.

Qual è il modo corretto di gestire gli spazi dei nomi in questa situazione?

È stato utile?

Soluzione

L'uso di LocalName dovrebbe andare bene. Non lo considererei affatto un hack se non ti interessa in quale spazio dei nomi si trova.

Se conosci lo spazio dei nomi che desideri e vuoi specificarlo, puoi:

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

( Riferimento MSDN )

Puoi anche ottenere un elenco di tutti gli spazi dei nomi utilizzati nel documento:

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

Suppongo che potresti usarlo per farlo, ma in realtà non è affatto un trucco:

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

Altri suggerimenti

Se sai che lo spazio dei nomi verrà dichiarato dall'elemento root dell'XML, come spesso accade, puoi farlo:

var ns = xDoc.Root.Name.Namespace;
var x = xDoc.Descendants(ns + "div");
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top