Пространства имен XElement (как это сделать?)

#c# #xml #linq #namespaces

#c# #xml #linq #пространства имен

Вопрос:

Как создать xml-документ с префиксом узла, например:

 <sphinx:docset>
  <sphinx:schema>
    <sphinx:field name="subject"/>
    <sphinx:field name="content"/>
    <sphinx:attr name="published" type="timestamp"/>
 </sphinx:schema>
  

Когда я пытаюсь запустить что-то вроде new XElement("sphinx:docset") , я получаю исключение

Необработанное исключение: System.Xml.XmlException: Символ ‘:’ с шестнадцатеричным значением 0x3A не может быть включен в имя.
в System.Xml.XmlConvert.VerifyNCName(имя строки, тип исключения exceptionTyp e)
в System.Xml.Linq.XName..ctor(пространство имен ns, строка localName)
в System.Xml.Linq.Пространство имен.getName(строковое локальное имя)
в System.Xml.Linq.XName.Get(расширенное имя строки)

Комментарии:

1. Взгляните на XmlNamespaceManager класс.

2. Ваш документ был бы недействительным. Необходимо объявить sphinx префикс.

Ответ №1:

Это действительно просто в LINQ to XML:

 XNamespace ns = "sphinx";
XElement element = new XElement(ns   "docset");
  

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

 XNamespace ns = "http://url/for/sphinx";
XElement element = new XElement("container",
    new XAttribute(XNamespace.Xmlns   "sphinx", ns),
    new XElement(ns   "docset",
        new XElement(ns   "schema"),
            new XElement(ns   "field", new XAttribute("name", "subject")),
            new XElement(ns   "field", new XAttribute("name", "content")),
            new XElement(ns   "attr", 
                         new XAttribute("name", "published"),
                         new XAttribute("type", "timestamp"))));
  

Это приводит к:

 <container xmlns:sphinx="http://url/for/sphinx">
  <sphinx:docset>
    <sphinx:schema />
    <sphinx:field name="subject" />
    <sphinx:field name="content" />
    <sphinx:attr name="published" type="timestamp" />
  </sphinx:docset>
</container>
  

Комментарии:

1. спасибо, но для первой версии я получил <docset xmlns=»sphinx» /> это не то, что я хочу ;)))

2. @Edward83: Смотрите мой другой пример. В принципе, вам нужно, чтобы пространство имен было указано где-нибудь в xmlns…

3. После всех уродливых взломов, которые я использовал для этого (рекурсивные статические методы для присоединения пространства имен ко всему)… Сначала я попробовал этот подход, но я не поставил префикс XNamespace. Xmlns во внешнее пространство имен. Зачем вообще нужен этот префикс? Устанавливает ли он его для глобального?

4. @micahhoover: Вам следует ознакомиться со спецификацией пространства имен W3C. Мне не совсем ясно, чего вы пытались достичь, или что пошло не так.

Ответ №2:

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

 XDocument xml = XDocument.Load(address);
XNamespace ns = xml.Root.Name.Namespace;
foreach (XElement el in xml.Descendants(ns   "whateverYourElementNameIs"))
    //do stuff
  

Комментарии:

1. Хороший подход ( 1)! Однако у меня это не сработало в случае, когда корневой XML-элемент имел несколько атрибутов xmlns, т. Е.: xmlns:soapenv=»…» xmlns=»…». С использованием xml.Root. Функция GetDefaultNamespace() действительно дала мне то, что я хотел, а именно значение простого атрибута xmlns =»…».