Как вы обрабатываете произвольные пространства имен при обращении к Linq в XML? - PullRequest
19 голосов
/ 08 октября 2008

У меня есть проект, в котором я беру некоторый особенно уродливый «живой» HTML и превращаю его в формальный XML DOM с помощью пакета Agility HTML. То, что я хотел бы сделать, - это запросить это с помощью Linq to XML, чтобы я мог вычеркнуть нужные мне биты. Я использую метод, описанный здесь , чтобы проанализировать HtmlDocument в XDocument, но при попытке выполнить запрос по этому вопросу я не уверен, как обращаться с пространствами имен. В одном конкретном документе исходный HTML был на самом деле плохо отформатированный XHTML со следующим тегом:

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

При попытке сделать запрос из этого документа кажется, что атрибут namespace мешает мне сделать что-то вроде:

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

Очевидно, что для этих тегов "div" только LocalName является "div", но правильное имя тега - это пространство имен плюс "div". Я попытался провести некоторое исследование по проблеме пространств имен XML, и кажется, что я могу обойти пространство имен, выполнив запрос следующим образом:

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

Однако это выглядит довольно хакерским решением и неправильно решает проблему пространства имен. Насколько я понимаю, надлежащий XML-документ может содержать несколько пространств имен, и поэтому правильным способом его обработки является анализ пространств имен, к которым я обращаюсь. Кто-нибудь еще должен был сделать это? Я просто пробираюсь к сложному? Я знаю, что мог бы избежать всего этого, просто придерживаясь HtmlDocument и обращаясь к XPath, но я бы предпочел придерживаться того, что я знаю (Linq), если это возможно, и я также предпочел бы знать, что я не настраиваю себя на дальнейшее пространство имен. связанные с этим вопросы в будущем.

Как правильно обращаться с пространствами имен в этой ситуации?

Ответы [ 3 ]

17 голосов
/ 08 октября 2008

Использование LocalName должно быть в порядке. Я бы не стал считать это хаком, если вам все равно, в каком пространстве имён.

Если вы знаете желаемое пространство имен и хотите его указать, вы можете:

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

( MSDN, ссылка )

Вы также можете получить список всех пространств имен, используемых в документе:

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

Полагаю, вы могли бы использовать это для этого, но на самом деле это не так уж и мало:

var x = namespaces.SelectMany(ns=>xDoc.Root.Descendants(ns+"div"));
2 голосов
/ 06 августа 2012

Если вы знаете, что пространство имен будет объявлено корневым элементом XML, как это чаще всего бывает, вы можете сделать это:

var ns = xDoc.Root.Name.Namespace;
var x = xDoc.Descendants(ns + "div");
0 голосов
/ 08 октября 2008

Я думаю, что ваш Google-фу не подойдет вам:

http://www.google.com.au/search?hl=en&q=linq+xml+namespaces

...