【问题标题】:Remove unwanted (empty) xmlns attribute added by appendChild删除 appendChild 添加的不需要的(空的)xmlns 属性
【发布时间】:2012-10-24 13:54:52
【问题描述】:

我有这个代码:

function setupProject($projectFile) {
  [xml]$root = Get-Content $projectFile;

  $project = $root.Project;

  $beforeBuild = $root.CreateElement("Target", "");
  $beforeBuild.SetAttribute("name", "BeforeBuild");
  $beforeBuild.RemoveAttribute("xmlns");
  $project.AppendChild($beforeBuild);

  $root.Save($projectFile);
}

应该在 XML 文档中添加一个新的<Target name="BeforeBuild" />

但它也添加了一个我不想要的空 xmlns="" 属性。 (其实是Visual Studio不喜欢这个属性!)

<Target name="BeforeBuild" xmlns="" />

我已经尝试过这段代码:

$beforeBuild.RemoveAttribute("xmlns");
$project.AppendChild($beforeBuild);
$beforeBuild.RemoveAttribute("xmlns");

【问题讨论】:

    标签: xml dom powershell appendchild


    【解决方案1】:

    已添加 xmlns="" 命名空间 (un) 声明,因为您的父元素在命名空间中,而您的子元素不在。

    如果你不想添加这个命名空间声明,这意味着你希望子元素和它的父元素在同一个命名空间中,答案是在你创建元素的时候把它放在这个命名空间中.即更改调用CreateElement("Target", "") 以指定正确的命名空间。

    【讨论】:

    • 但我在(直接)父元素上没有任何命名空间。只有根元素&lt;Project&gt; 有一个:xmlns="http://schemas.microsoft.com/developer/msbuild/2003"。那么我应该将此值传递给CreateElement()吗?
    • 我看不到足够的代码来计算细节(无论如何我讨厌 DOM 编程),但序列化程序添加了 xmlns="" 声明这一事实非常清楚地证明了父级在命名空间中(无论出于何种原因),而子级不在。
    • 是的,您应该为新元素提供与项目根元素相同的命名空间。否则会添加 xmlns 属性,因为命名空间与父命名空间不同。
    • 更好的答案 - 通过指定正确的命名空间来解决问题,然后它就会消失(因为它是冗余信息)
    • 解决了我的问题。我为这个问题奋斗了 4 个小时
    【解决方案2】:

    作为answered by Michael Kay,删除这个不需要的命名空间的最佳方法是在与其父元素相同的命名空间中创建新的子元素:

    function setupProject($projectFile) {
      [xml]$root = Get-Content $projectFile;
    
      $project = $root.Project;
    
      # UPDATE THIS LINE $beforeBuild = $root.CreateElement("Target", "");
      $beforeBuild = $root.CreateElement("Target", $project.NamespaceURI);
      $beforeBuild.SetAttribute("name", "BeforeBuild");
      $beforeBuild.RemoveAttribute("xmlns");
      $project.AppendChild($beforeBuild);
    
      $root.Save($projectFile);
    }
    

    【讨论】:

      【解决方案3】:

      检查这些以获得可能的解决方案:

      Powershell and csproj

      Xml namespace and C# csproj

      这是适用于 OP 的第二种解决方案的解决方法:

      $content = [xml] $content.OuterXml.Replace(" xmlns=`"`"", "")
      $content.Save($_.FullName);
      

      【讨论】:

      • 感谢您的链接!第二个解决方案对我有用。您能否将该代码 sn-p 插入您的答案中?这对其他用户会很有帮助。
      • 错误的答案 - 它可能有效,但它表明对问题原因存在根本性的误解。
      • @MichaelKay:错误的态度 - 一个有效的答案就是一个好的答案。如果您可以提出更好的建议,请继续(您已经这样做了)。
      【解决方案4】:

      使用 Javascript

      如果您使用 JS 创建 XML 文档,并且在父节点上声明 xmlns="XXXX" 后在子节点上获得空白 xmlns 属性,请使用 JS createElementNS(namespace, nodeName) 而不是 createElement(nodeName)

      这是假设您希望您的子节点与父节点共享相同的命名空间。在下面的情况下,'v1','v2'等将共享'data'的NS

      看起来像这样:

      let data = someArray;
      let nameSpace = 'XXX';
      let doc = "<?xml version='1.0' encoding='utf-8' ?><data xmlns='XXXX'></data>";
      let parser = new DOMParser();
      let xml = parser.parseFromString(doc, "text/xml");
      
      for (let i = 0; i < data.length; i++) {
          let node = xml.createElementNS(nameSpace , "v" + (i + 1));
          $(node).text(data[i]);
          let elements = xml.getElementsByTagName("data");
          elements[0].appendChild(node);
       }
      

      正确的结果如下所示:

      <?xml version='1.0' encoding='utf-8' ?>
      <data xmlns='XXXX'>
          <v1></v1>
          <v2></v2>
      </data>
      

      与坏结果:

      <?xml version='1.0' encoding='utf-8' ?>
      <data xmlns='XXXX'>
          <v1 xmlns=""></v1>
          <v2 xmlns=""></v2>
      </data>
      

      使用此解决方案,您还可以为您的子节点声明单独的命名空间。只需将 nameSpace 变量替换为不同的命名空间 uri 字符串或另一个设置变量。

      【讨论】:

        【解决方案5】:

        命名空间是每个节点名称的固有部分。删除命名空间意味着需要重新创建节点。这是代码,您可以在其中创建没有 Namespace 属性的子节点。

        这意味着如果您的主标签包含命名空间属性而您的子节点没有。因此,子节点将从父节点继承默认的命名空间属性。 删除命名空间属性的最佳方法是

        [xml]$oXMLDocument = (Get-Content "D:\myXml.xml")
        # Assuming Project is the parent node with a namespace
        $project = $oXMLDocument.Project
        $childNode = $oXMLDocument.CreateElement("test",$project.NamespaceURI)
        # (Optional) Add any attributes to the element
        $childNode.SetAttribute("name", "value")
        $oXMLDocument.DocumentElement.AppendChild($childNode)
        # Save the document
        $oXMLDocument.Save("D:\myXml2.xml")
        

        基本上,这不会从子笔记中删除命名空间属性。事实上你不能。这会将属性隐藏为默认值

        如果你需要在你的子节点下创建子子节点,那么按照相同的样式。

        【讨论】:

        • code 似乎与accepted answer 中的几乎相同,而您的解释 让我觉得不如@ 中的那个987654322@ 接受的链接到。你认为你的回答有什么贡献?
        【解决方案6】:

        命名空间是每个节点名称的固有部分。删除命名空间意味着需要重新创建节点。 这是代码,您可以在其中创建没有 Namespace 属性的子节点。

        [xml]$oXmlDocume = [xml] (Get-Content  D:\myXml.xml)
        // Assuming Project is the parent node
        $project = $oXMLDocument.Project
        $childNode = $oXMLDocument.CreateElement("Child",$project.NamespaceURI)
        $0XMLDocument.AppendChild($ChildNode)
        

        如果你需要在你的子节点下创建子子节点,那么按照相同的样式。

        【讨论】:

        • 看来你后来发了another answer这只是对这个的更新,所以我建议删除这个。
        【解决方案7】:

        我在 VBA 中构建网站地图时遇到了这个问题,但 @Neolisk 让我走上了正轨。这解决了我的问题:

        'replace the empty attribute with nothing and load it back into the XML source
        myTree.LoadXML Replace(myTree.XML, " xmlns=""""", "")
        
        'Write that XML to a file
        myTree.Save xmlFileName
        

        感谢您的帮助,@Neolisk!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-12-10
          • 1970-01-01
          • 1970-01-01
          • 2018-08-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多