none
Linq to XML. Префиксы для пространства имён по умолчанию. RRS feed

  • Вопрос

  • Копался с Linq to XML и столкнулся с таким странным поведением:
    using System;
    using System.Xml.Linq;
    internal static class Test{
        private static void Main(){
            const string xmlString1="<ElementName xmlns=\"NamespaceName\" xmlns:prefix=\"NamespaceName\" prefix:AttributeName=\"AttributeValue\" />";
            const string xmlString2="<ElementName xmlns:prefix=\"NamespaceName\" xmlns=\"NamespaceName\" prefix:AttributeName=\"AttributeValue\" />";
            Console.WriteLine(XElement.Parse(xmlString1).ToString());
            Console.WriteLine(XElement.Parse(xmlString2).ToString());
        }
    }
    На выходе получаем:
    <prefix:ElementName xmlns="NamespaceName" xmlns:prefix="NamespaceName" prefix:AttributeName="AttributeValue" />
    <ElementName xmlns:prefix="NamespaceName" xmlns="NamespaceName" prefix:AttributeName="AttributeValue" />
    В первом случае к имени элемента добавляется, совершенно ненужный, префикс. Зачем, спрашивается, пространство имён по умолчанию декларировали. Такое поведение сохраняется и для вложенных элементов. То есть, если префикс для пространства имён по умолчанию определён после самого пространства имён по умолчанию, то он добавляется к именам элементов. Можно ли как-то управлять этим поведение, кроме изменения порядка атрибутов?
    23 марта 2013 г. 17:28

Ответы

  • Судя по коду XElement.ToString()/ElementWriter.WriteElement/ - никак, там явно идет перебор по всем аттрибутам, с проверкой IsNamespaceDeclaration, с отдачей приоритета последнему встреченному.
    • Помечено в качестве ответа PetSerAl 28 марта 2013 г. 18:33
    28 марта 2013 г. 18:06
    Модератор

Все ответы

  • Здравствуйте,

    Думаю что можно, смотрите здесь:

    How to: Control Namespace Prefixes (C#) (LINQ to XML)

    25 марта 2013 г. 15:09
    Модератор
  • По приведённой Вами ссылке только информация о назначении префиксов для пространств имён. Примеров, когда одно и тоже пространство имён используется, как пространство имён по умолчанию, а также ему назначен некоторый префикс, в документации я не нашёл.
    25 марта 2013 г. 16:21
  • По приведённой Вами ссылке только информация о назначении префиксов для пространств имён. Примеров, когда одно и тоже пространство имён используется, как пространство имён по умолчанию, а также ему назначен некоторый префикс, в документации я не нашёл.

    Если я правильно Вас понял: How to set the default XML namespace for an XDocument  

    How to: Create a Document with Namespaces (C#) (LINQ to XML) , есть и по заданию префикса.

    А если не правильно, то опишите более конкретно какова Ваша цель :)


    26 марта 2013 г. 7:57
    Модератор
  • Если конкретно, то я хотел бы знать можно ли, и если можно, то как породить такой XElement, чтобы при вызове ToString() получалась следующая строка:

    <ElementName xmlns="NamespaceName" xmlns:prefix="NamespaceName" />
    Конкретные требования к строке:
    1. Имя элемента должно быть без префикса, так как оно лежит в пространстве имён по умолчанию.
    2. Должно присутствовать определение пространства имён по умолчанию и определение префикса для того же самого пространства имён.
    3. Определение пространства имён по умолчанию должно идти до определения префикса.
    26 марта 2013 г. 11:25
  • Как указанно здесь:

    Handling names, namespaces, and namespace prefixes is generally a complex part of XML programming. LINQ to XML simplifies names and namespaces by eliminating the requirement to deal with namespace prefixes. If you want to control namespace prefixes, you can. But if you decide to not explicitly control namespace prefixes, LINQ to XML will assign namespace prefixes during serialization if they are required, or will serialize using default namespaces if they are not. If default namespaces are used, there will be no namespace prefixes in the resulting document. For more information, see Working with XML Namespaces.

    Так что по сериалайзеру:

    XmlSerializer Producing XML With No Namespace Prefix

    26 марта 2013 г. 15:56
    Модератор
  • Я знаю как в Linq to XML назначать пространству имён конкретный префикс и знаю как назначать некоторое пространство имён пространством имён по умолчанию. Я не знаю как в Linq to XML контролировать использование префикса, если пространству имён назначен префикс и тоже самое пространство имён используется как пространство имён по умолчанию, кроме как изменять порядок соответствующих атрибутов. И я спрашиваю: если ли в Linq to XML такой способ или его нет. Пожалуйста обратите внимание на выделенный текст: ни по одной из Ваших ссылок нет примера, где бы это условие выполнялось.
    26 марта 2013 г. 16:37
  • Я знаю как в Linq to XML назначать пространству имён конкретный префикс и знаю как назначать некоторое пространство имён пространством имён по умолчанию. Я не знаю как в Linq to XML контролировать использование префикса, если пространству имён назначен префикс и тоже самое пространство имён используется как пространство имён по умолчанию, кроме как изменять порядок соответствующих атрибутов. И я спрашиваю: если ли в Linq to XML такой способ или его нет. Пожалуйста обратите внимание на выделенный текст: ни по одной из Ваших ссылок нет примера, где бы это условие выполнялось.

    Надеюсь правильно понял:

    XElement ElementName = XElement.Parse(
        @"<a:ElementName xmlns:a='NamespaceName'
                  xmlns:c='NamespaceName'>
            <c:Child>1</c:Child>
          </a:ElementName>");
    ElementName.DescendantsAndSelf().Attributes().Where(n => n.IsNamespaceDeclaration).Remove();
    ElementName.Add(
        new XAttribute("xmlns", "NamespaceName"),
        new XAttribute(XNamespace.Xmlns + prefix, "NamespaceName"));
    Console.WriteLine(ElementName);

    На выходе получаем:

    <ElementName xmlns="NamespaceName"
          xmlns:prefix="NamespaceName">
      <prefix:Child>1</prefix:Child>
    </ElementName>



    27 марта 2013 г. 9:46
    Модератор
  • В том то и дело, что на выходе мы получаем не
    <ElementName xmlns="NamespaceName" xmlns:prefix="NamespaceName" ...
    а
    <prefix:ElementName xmlns="NamespaceName" xmlns:prefix="NamespaceName" ...
    27 марта 2013 г. 10:10
  • А зачем в этом случае вообще добавлять префикс? Какой в нем смысл?

    Т.е. если вы его добавили - то L2X решает что стоит его везде прописать (вы же сами сказали "нужен префикс"). Если не добавили - то не пропишет, просто будет использовать его по умолчанию:

    XNamespace ns = @"http://mynamespace";
    var result = new XDocument(
        new XElement("root",
            new XElement(ns + "custom",
                new XElement(ns + "inner"),
                new XElement(ns + "inner")
                )
            )
        );

    <root>
      <custom xmlns="http://mynamespace">
        <inner />
        <inner />
      </custom>
    </root>



    27 марта 2013 г. 10:24
    Модератор
  • Как мне указать имя атрибута в пространстве имён без префикса?
    27 марта 2013 г. 10:26
  • var result = new XDocument(
        new XElement("root",
            new XElement(ns + "custom",
                new XAttribute(ns + "someattr_in_ns", "val1")
                )
            )
        );
    

    на выходе:

    <root>
      <custom p2:someattr_in_ns="val1" xmlns:p2="http://mynamespace" xmlns="http://mynamespace" />
    </root>

    28 марта 2013 г. 9:08
    Модератор
  • ... или если очень хочется именно кастомный префикс, то добавляйте дефолтный namespace после префикса:

    var result = new XDocument(
        new XElement("root",
            new XElement(ns + "custom",
                new XAttribute(ns + "someattr_in_ns", "val1"),
                new XAttribute(XNamespace.Xmlns + "test", ns),
                new XAttribute("xmlns", ns),
                new XElement(ns + "inner"),
                new XElement(ns + "inner")
                )
            )
        );
    

    <root>
      <custom test:someattr_in_ns="val1" xmlns:test="http://mynamespace" xmlns="http://mynamespace">
        <inner />
        <inner />
      </custom>
    </root>

    28 марта 2013 г. 9:19
    Модератор
  • если очень хочется именно кастомный префикс, то добавляйте дефолтный namespace после префикса
    Проблема в том, что это не ответ на вопрос, заданный мною в самом первом посте:
    Можно ли как-то управлять этим поведение, кроме изменения порядка атрибутов?
    28 марта 2013 г. 13:01
  • Судя по коду XElement.ToString()/ElementWriter.WriteElement/ - никак, там явно идет перебор по всем аттрибутам, с проверкой IsNamespaceDeclaration, с отдачей приоритета последнему встреченному.
    • Помечено в качестве ответа PetSerAl 28 марта 2013 г. 18:33
    28 марта 2013 г. 18:06
    Модератор