【问题标题】:Creating XML Elements without namespace declarations创建没有命名空间声明的 XML 元素
【发布时间】:2019-11-28 22:10:57
【问题描述】:

我试图将新的“PropertyGroup”元素添加到以下 XML 文件中

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
  <PropertyGroup>
    <ProjectGuid>{00AA7ECA-95A0-0000-0000-AD4D2E056BFE}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>testnS</RootNamespace>
    <AssemblyName>testname</AssemblyName>
    <PluginId>4B84E5C0-EC2B-4C0C-8B8E-3FAEB09F74C6</PluginId>
  </PropertyGroup>
</Project>

我使用的代码如下(注意还有其他的逻辑被去掉了):

        XmlTextReader reader = new XmlTextReader(filename);
        XmlDocument doc = new XmlDocument();

        doc.Load(reader);
        reader.Close();

        XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable);
        ns.AddNamespace("x", "http://schemas.microsoft.com/developer/msbuild/2003");

        XmlElement root = doc.DocumentElement;
        XmlNode refNode = root.SelectSingleNode("x:Project", ns);

        root.SelectSingleNode("Project", ns);

        XmlElement newElement = doc.CreateElement("PropertyGroup", "http://schemas.microsoft.com/developer/msbuild/2003");
        newElement.InnerXml = "<value>test</value>";
        root.InsertAfter(newElement, refNode);
        doc.Save(filename);

这会在 XML 文档中生成以下新元素:

<PropertyGroup>
  <value xmlns="">test</value>
</PropertyGroup>

如何去掉元素上的命名空间声明?

【问题讨论】:

  • 这里必须使用 InnerXml 属性吗?明确地做到这一点会更容易。 (如果可以的话,使用 LINQ to XML 会更容易。)
  • 不确定 LINQ to XML - LINQ 对我来说是未知数... :-)
  • 但是我刚刚发现了这个:stackoverflow.com/questions/2013165/…
  • CreateElement 调用中的命名空间是否绝对必要?

标签: c# xml


【解决方案1】:

您需要为添加到 DOM 的 所有 元素指定 XML 命名空间:

XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable);
ns.AddNamespace("x", "http://schemas.microsoft.com/developer/msbuild/2003");

XmlElement root = doc.DocumentElement;
XmlNode refNode = root.SelectSingleNode("x:Project", ns);

XmlElement newElement = doc.CreateElement(
    "PropertyGroup",
    "http://schemas.microsoft.com/developer/msbuild/2003");
var value = newElement.AppendChild(doc.CreateElement(
    "value",
    "http://schemas.microsoft.com/developer/msbuild/2003"));
value.AppendChild(doc.CreateTextNode("test"));

root.InsertAfter(newElement, refNode);

如果您不对任何元素执行此操作(或者如果您使用 InnerXml 之类的),则该元素将获得可怕的空命名空间。

【讨论】:

    【解决方案2】:

    发生这种情况的原因是您通过在根节点上定义了命名空间,将文档的默认命名空间定义为“http://schemas.microsoft.com/developer/msbuild/2003”:

    xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
    

    然后您继续向文档中添加一个不在命名空间(“null”命名空间)中的元素。这个必须

    限定
    xmlns=""
    

    因为如果不是,则意味着新元素位于前面提到的 Microsoft 命名空间中 - 它不是(或者更确切地说 - 你没有要求它存在)。

    所以要么:

    • 您实际上希望新元素 位于 Microsoft 命名空间中 - 在 哪种情况你需要这么说。这 最简单的方法是使用 createElement 并提供命名空间,虽然 您可能可以明确说明 在你的 xmlns 属性 InnerXml(这不是一个特别 添加节点的好方法)。

    • 你确实想要这个元素 null 命名空间,在这种情况下,您 可能比排位赛更好 不在的其他节点 带有命名空间的空命名空间 前缀。

    我怀疑你想要前者。

    可以在here 找到有关命名空间的快速概述。

    【讨论】:

      【解决方案3】:

      为避免在新创建的元素中出现额外的xmlns="" 属性,您可以将根命名空间作为参数传递:

       $child = $doc.CreateElement("value", $doc.DocumentElement.NamespaceURI);
       $res = $doc.PropertyGroup.AppendChild($child); # res here to avoid extra output
      

      这将导致

      <PropertyGroup>
          <value></value>
      </PropertyGroup>
      

      【讨论】:

        猜你喜欢
        • 2015-09-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-24
        • 1970-01-01
        • 2016-10-30
        • 1970-01-01
        相关资源
        最近更新 更多