XElement добавляет xmlns - PullRequest
       24

XElement добавляет xmlns

12 голосов
/ 03 декабря 2010

Я использую Linq to XML для создания нового XML-файла. Некоторую часть файла я получаю из существующего XML-файла. Я использую следующий код для этого.

var v2 = new XDocument(
  new XDeclaration("1.0", "utf-16", ""),
  new XComment(string.Format("Converted from version 1. Date: {0}", DateTime.Now)),
  new XElement(ns + "keyem",
    new XAttribute(XNamespace.Xmlns + "xsd", xsd.NamespaceName),
    new XAttribute(XNamespace.Xmlns + "xsi", xsi.NamespaceName),
    new XAttribute(xsi + "schemaLocation", schemaLocation.NamespaceName),
    new XAttribute("version", "2"),
    new XAttribute("description", description),
    new XElement(ns + "layout",
      new XAttribute("type", type),
      new XAttribute("height", height),
      new XAttribute("width", width),
      settings.Root)       // XML from an existing file

Проблема в том, что он добавляет xmlns = "" первый элемент из существующего файла.

Результат:

<?xml version="1.0" encoding="utf-16"?>
<foo 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://tempuri.org/KeyEmFileSchema.xsd KeyEmFileSchema.xsd"
  xmlns="http://tempuri.org/KeyEmFileSchema.xsd">
  <settings xmlns="">
      ...
  </settings>
</foo>

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

<?xml version="1.0" encoding="utf-16"?>
<settings>
  <colormaps>
    <colormap color="Gray"     textcolor="Black"/>
    <colormap color="DarkGray" textcolor="White"/>
    <colormap color="Black"    textcolor="White"/>
    <colormap color="Cyan"     textcolor="Black"/>
  </colormaps>
  <macromaps>
    <macromap pattern="^@([0-9A-F]{2})\|([0-9A-F]{2})$"  replace="{ESC}$1{ESC}$2{MOUSERESET}"/>
    <macromap pattern="^\$([0-9A-F]{2})\|([0-9A-F]{2})$" replace="{USERCLICK}{ESC}$1{ESC}$2{MOUSERESET}"/>
    <macromap pattern="^\$([0-9A-F]{2})$"                replace="{USERCLICK}{ESC}$1"/>
  </macromaps>
  <keydefault color="Cyan"/>
  <groupdefault color="DarkGray"/>
</settings>

Ответы [ 2 ]

12 голосов
/ 03 декабря 2010

Вы видите это, потому что элемент настроек (предположительно исходящий из вашего документа) не находится в этом пространстве имен.Он находится в пространстве имен по умолчанию / null-uri.

Вам потребуется преобразовать входной документ, чтобы изменить его пространство имен.

В этом несколько упрощенном примере ваш файл XML помещается вдругой документ, но, прежде чем он это сделает, он меняет пространство имен каждого элемента в этом XML-файле на пространство имен целевого документа ...

    static void ProcessXmlFile()
    {
        XNamespace ns = "http://tempuri.org/KeyEmFileSchema.xsd/";

        // load the xml document
        XElement settings = XElement.Load("data.xml");

        // shift ALL elements in the settings document into the target namespace
        foreach (XElement e in settings.DescendantsAndSelf())
        {
            e.Name = ns + e.Name.LocalName;
        }

        // write the output document
        var file = new XDocument(new XElement(ns + "foo",
                                        settings));

        Console.Write(file.ToString());            
    }

В результате чего это ...

<foo xmlns="http://tempuri.org/KeyEmFileSchema.xsd/">
  <settings>
    <colormaps>
      <colormap color="Gray" textcolor="Black" />
      <colormap color="DarkGray" textcolor="White" />
      <colormap color="Black" textcolor="White" />
      <colormap color="Cyan" textcolor="Black" />
    </colormaps>
    <macromaps>
      <macromap pattern="^@([0-9A-F]{2})\|([0-9A-F]{2})$" replace="{ESC}$1{ESC}$2{MOUSERESET}" />
      <macromap pattern="^\$([0-9A-F]{2})\|([0-9A-F]{2})$" replace="{USERCLICK}{ESC}$1{ESC}$2{MOUSERESET}" />
      <macromap pattern="^\$([0-9A-F]{2})$" replace="{USERCLICK}{ESC}$1" />
    </macromaps>
    <keydefault color="Cyan" />
    <groupdefault color="DarkGray" />
  </settings>
</foo>

Как видите, элемент settings теперь находится в том же пространстве имен, что и элемент foo.По сути, это быстрое и грязное преобразование XML, и оно явно не учитывает пространства имен в импортируемом документе XML.Но это может быть то, что вам нужно, или, по крайней мере, может послужить основой чего-то более надежного.

2 голосов
/ 12 февраля 2018

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

public static XElement EnsureNamespaceExists(this XElement xElement, XNamespace xNamespace)
{
    string nodeName = xElement.Name.LocalName;

    if (!xElement.HasAttribute("xmlns"))
    {
        foreach (XElement tmpElement in xElement.DescendantsAndSelf())
        {
            tmpElement.Name = xNamespace + tmpElement.Name.LocalName;
        }
        xElement = new XElement(xNamespace + nodeName, xElement.FirstNode);
    }

    return xElement;
}
...