XElement добавляет только префикс

#c# #.net #xml #linq-to-xml

#c# #.net #xml #linq-to-xml

Вопрос:

У меня есть XML-файл, подобный:

 <myPrefix:Catalog xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
 xmlns:sys="clr-namespace:System;assembly=mscorlib" 
 xmlns:myPrefix="clr-namespace:........">

  <myPrefix:Item Name="Item1" Mode="All" />
  <myPrefix:Item Name="Item2" Mode="Single" />

</myPrefix:Catalog>
  

С помощью C # я создаю новый элемент, подобный:

 XContainer container = XElement.Parse(xml);
XElement xmlTree = 
   new XElement("Item",
      new XAttribute("Name", item.Name),
      new XAttribute("Mode", item.Mode));
  

Как вы можете видеть, я не добавляю префикс «myPrefix». Кто-нибудь может сказать мне, как я могу это сделать? Я не хочу снова объявлять xmlns. Спасибо, Питер

Ответ №1:

     XElement container = XElement.Parse(xml);
    XNamespace myPrefix = container.GetNamespaceOfPrefix("myPrefix");

    XElement xmlTree = new XElement(myPrefix   "Item",     
                            new XAttribute("Name", item.Name), 
                            new XAttribute("Mode", item.Mode));

    container.Add(xmlTree);
  

Ответ №2:

Редактировать 1:
Если вы добавите атрибут пространства имен также к элементу, это заставит его добавить префикс. Но в конечном итоге вы все равно получаете атрибут xmlns в узле. Чтобы удалить его, вам, вероятно, как говорит Джефф, потребуется использовать XmlWriter.

Правка 2:
Чтобы получить ТОЧНЫЙ XML, который вы хотите, вам также необходимо создать корневой элемент:

Правка 3:
ОК. Я нашел способ получить то, что вы хотите, без XmlWriter:

 var xml = "<myPrefix:Catalog xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:myPrefix="clr-namespace:........"><myPrefix:Item Name="Item1" Mode="All" /></myPrefix:Catalog>";

XNamespace presentation = "http://schemas.microsoft.com/winfx/2006/xaml/presentation";
XNamespace xaml = "http://schemas.microsoft.com/winfx/2006/xaml";
XNamespace mscorlib = "clr-namespace:System;assembly=mscorlib";
XNamespace myPrefix = "clr-namespace:.......";

XElement container = XElement.Parse(xml);

var xmlTree = new XElement("Item",
               new XAttribute("Name", "Item2"),
               new XAttribute("Mode", "Single"));

container.Add(xmlTree);

foreach (var el in container.DescendantsAndSelf())
{
  el.Name = myPrefix.GetName(el.Name.LocalName);
  var atList = el.Attributes().ToList();
  el.Attributes().Remove();
  foreach (var at in atList)
  {
    if (el.Name.LocalName == "Catalog" amp;amp; at.Name.LocalName != "xmlns")
      continue;
    el.Add(new XAttribute(at.Name.LocalName, at.Value));
  }
}

container.Add(new XAttribute(XNamespace.Xmlns   "x", xaml));
container.Add(new XAttribute(XNamespace.Xmlns   "sys", mscorlib));
container.Add(new XAttribute(XNamespace.Xmlns   "myPrefix", myPrefix));
  

Правка 4:
Очевидно, был более простой способ … намного проще… смотрите другие ответы.

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

1. Спасибо за ваш ответ, но это не сработает. Результат выглядит следующим образом: <Имя элемента=»Item3″ Mode=»Single» xmlns=»clr-пространство имен:…….» />

2. @Peter: Это будет выглядеть именно так, если элемент является корневым. Если это не корень, то у него будет префикс, если пространство имен объявлено в предке.

3. @Peter: Именно так работает сериализатор LINQ to XML. Я не знаю, возможно ли это вообще, не возвращаясь назад и не используя XmlWriter .

4. @Джефф, хм, спасибо, хорошо. Может быть, кто-нибудь знает способ, и я попробую XmlWriter.

5. @Sani большое спасибо! У меня это работает 🙂 Теперь мне нужно только удалить xmlns.

Ответ №3:

Вам необходимо создать любые новые элементы в пространстве имен. Предполагая, что вы знаете префикс пространства имен, которое вы хотите использовать в образце XML, тогда сделайте это следующим образом:

     var xml = "<myPrefix:Catalog xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:myPrefix="clr-namespace:........"><myPrefix:Item Name="Item1" Mode="All" /></myPrefix:Catalog>";

    XElement catalog = XElement.Parse(xml);

    XNamespace myP = catalog.GetNamespaceOfPrefix("myPrefix");

    catalog.Add(new XElement(myP   "Item", new XAttribute("Name", "foo"), new XAttribute("Mode", "bar")));