Атрибут xmlns не даёт получить XElement

192
14 июля 2018, 19:00

Работаю в Visual Studio 2017, проект на c#. Имеется XML файл, который пытаюсь распарсить с помощью стандартной библиотеки System.Xml.Linq. Вот текст файла

<?xml version="1.0" encoding="utf-8"?>
<SCL version="2007" revision="A"
 xmlns="http://www.iec.ch/61850/2003/SCL"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.iec.ch/61850/2003/SCL
C:\Data\sdps\SCL3.0\SCL.xsd">
   <!-- Содержимое элемента -->
</SCL>

Вот код:

static void Main(string[] args)
{
    XDocument xdoc = XDocument.Load(args[0]);
    XElement xe = xdoc.Element("SCL");
    if (xe == null)
    {
        Exit("Отсутствует элемент \"SCL\"");
        return;
    }
    //...
}

Если в xml присутствует строка

xmlns="http://www.iec.ch/61850/2003/SCL"

то

xe == null

а если эту строку удалить, то 'xe' будет иметь содержимое, которое ожидается получить.

Почему так происходит и как-то можно нормально парсить xml с наличием строки "xmlns="http://www.iec.ch/61850/2003/SCL""?

Answer 1

Полное имя тэга (Qualified Name, QName) состоит из двух частей - локального имени ("SCL") и пространства имен ("http://www.iec.ch/61850/2003/SCL"). Для того чтобы найти тэг по имени - вам нужно указать обе части.

Сделать это можно разными способами, вот некоторые:

xdoc.Element("{http://www.iec.ch/61850/2003/SCL}SCL");
xdoc.Element(XName.Get("SCL", "http://www.iec.ch/61850/2003/SCL"));
XNamespace NS = "http://www.iec.ch/61850/2003/SCL";
xdoc.Element(NS + "SCL");

Также на всякий случай напоминаю, что атрибут xmlns в языке XML задает так называемое пространство имен по умолчанию, которое автоматически применяется ко всем дочерним элементам (но не применяется к атрибутам!)

Answer 2

Как правильно написал @Pavel Mayorov в соседнем ответе для выбора элемента необходимо указывать помимо локального имени еще и пространство имен, но если вы не хотите его указывать или не знаете его, можно воспользоваться возможностями Linq:

XElement xe = xdoc.Elements().SingleOrDefault(e => e.Name.LocalName == "SCL");
Console.WriteLine(xe);

Т.е. перебираем все элементы (.Elements()) и выбираем среди них тот, у которого локальное имя имеет значение "SCL" (.SingleOrDefault(...))

READ ALSO
C# делегаты и анонимные функции

C# делегаты и анонимные функции

Имеется следующий блок кода :

210
c# график функции

c# график функции

Нужно построить Y=4*X+8*COS(4*X) Однако получается не очень правдоподобноКак подобрать параметры?

235
C# WPF AvalonDock

C# WPF AvalonDock

Устанавливаю AvalonDock через NuGet и все нормально работает, но я бы хотел использовать source code в проектеКопирую классы и все остальное и VS 2017 видит...

219