XElement 添加一个 xmlns

发布于 2024-10-05 22:10:09 字数 2053 浏览 5 评论 0原文

我正在使用 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>

I'm using Linq to XML to create a new XML file. Some part of the file do I get from an existing XML file. I use the following code for this.

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

The problem is that it adds xmlns = "" the first element from the existing file.

The result is:

<?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>

The XML file I'm reading from looks like this, but I can change it if needed

<?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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

薯片软お妹 2024-10-12 22:10:09

您看到这一点是因为设置元素(可能来自您的文档)不存在于该命名空间中。它位于 default/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 文档中的任何名称空间。但这可能就是您所追求的,或者至少可能构成更强大的东西的基础。

You're seeing this because the settings element (presumably coming from your document) does not live in this namespace. It lives in the default/null-uri namespace.

You would need to transform your input document in order to change it's namespace.

This somewhat simplified example take your xml file and places it into another document but, before it does so, it changes the namespace of every element in that xml file to that of your target document...

    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());            
    }

The result of which this...

<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>

As you can see, the settings element is now in the same namespace as the foo element. This is essentially a quick and dirty xml transform, and clearly it doesn't respect any namespaces in the xml doc you're importing. But this might be what you're after, or might at least form the basis of something more robust.

以酷 2024-10-12 22:10:09

您可以为此编写一个扩展方法。
此方法有一个返回值,因此它支持链接,但也更改了原始方法的转换,因此无需赋值即可使用。

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;
}

You could write an extension method for this.
This method has a return value so it supports chaining, but also changes transformation of the original so it can be used without assignment.

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文