2010-03-11 7 views
1

Так что я пытаюсь разобрать файл XML:Почему XElement падает при анализе xml-файла с помощью xmlns?

<?xml version="1.0" encoding="utf-8" ?> 
<Root>  
    <att1 name="bob" age="unspecified" xmlns="http://foo.co.uk/nan">  
    </att1>  
</Root> 

Используя следующий код:

XElement xDoc= XElement.Load(filename); 
var query = from c in xDoc.Descendants("att1").Attributes() select c; 
foreach (XAttribute a in query) 
{ 
    Console.WriteLine("{0}, {1}",a.Name,a.Value); 
} 

Ничто не записывается в консоль, если я удалить Xmlns = "HTTP: // Foo. co.uk/nan "из xml-файла, после чего я получаю список имен атрибутов и значений, как и следовало ожидать, и, как мне нужно!

Редактировать: форматирование.

+0

Кстати, нет никакого смысла в письменном виде 'от с в любой избранной c'. – SLaks

+0

Так нет! Спасибо :) Я выбрал это из очень полезного введения в LINQ to XML здесь: http://www.microsoft.com/ru/msdn/nuggets/nugget/204/Querying-XML-in-C-with- LINQ-to-XML.aspx – zotty

ответ

3

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

XElement xDoc= XElement.Load(filename); 
XNamespace ns = "http://foo.co.uk/nan"; 
var query = from c in xDoc.Descendants(ns + "att1").Attributes() select c; 
foreach (XAttribute a in query) 
{ 
    Console.WriteLine("{0}, {1}",a.Name,a.Value); 
} 

Атрибуты не подцепить (xmlns=....) пространство имен по умолчанию, так что вам не нужно, чтобы квалифицировать их. Тег пространства имен (xmln:tags=....) является чисто локальным для использования документа или API, имена на самом деле являются пространством имен + локальное имя, поэтому вы всегда должны указывать пространство имен.

+0

Это сделало трюк отлично, спасибо. Поскольку пространство имен, скорее всего, изменится между файлами xml, я думаю, вы должны загрузить файл в виде строки, а затем искать пространство имен и объявить его в коде? – zotty

+0

@zotty Отсутствует синтаксический анализ строки, если вы запрашиваете LocalName, как показано в моем ответе. –

+0

@zotty: Если пространства имен меняются, ваш код будет более подробным, и на самом деле отсутствует точка пространства имен (имя узла - это пространство имен + локальное имя), но это иногда необходимо. – Richard

1

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

XNamespace ns = "http://foo.co.uk/nan"; 
foreach (XAttribute a in xDoc.Descendants(ns + "att1")) 
{ 
    Console.WriteLine("{0}, {1}",a.Name,a.Value); 
} 
2

Ваш призыв к Descendants запрашивает для элемента с именем «att1» не в пространстве имен.

Если вы вызвали Descendants("{http://foo.co.uk/nan}att1"), вы должны выбрать элемент с пространством имен, но не элемент, не содержащий имен.

Вы можете выбрать элементы, названные «att1» в какой-либо или нет имен, как это:

var query = from c in xDoc.Descendants() where c.Name.LocalName == "att1" select c.Attributes;