使用 LINQ to XML 删除属性不会持续存在

Posted

技术标签:

【中文标题】使用 LINQ to XML 删除属性不会持续存在【英文标题】:Removing attribute using LINQ to XML does not persists 【发布时间】:2012-08-07 15:28:26 【问题描述】:

我有以下 xml,我正在尝试使用 LINQ to XML 从中删除所有“xmlns”属性:

    <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
      <StackPanel>
        <LinearLayout xmlns="clr-namespace:androidAssembly;assembly=AndroidAssembly"/>                
        <TextView xmlns="clr-namespace:AndroidAssembly;assembly=AndroidAssembly">

  </StackPanel>
</Window>

使用以下代码。它为文档中的每个“xmlns”属性命中“attributesToRemove.Remove()”。但是当我保存文档时,我仍然拥有原始 XML。任何想法,可能是什么问题?

 var sr = new StringReader(richTextBoxOriginalXml.Text);
            XDocument xdoc = XDocument.Load(sr);            
            foreach(var node in xdoc.Descendants().ToList())
            
                var xmlns = node.Attributes().FirstOrDefault(a => a.Name == "xmlns");
                if (xmlns !=null)
                
                    var attributesToRemove = node.Attributes("xmlns").ToList();
                    attributesToRemove.Remove();
                
            

            var writer = new StringWriter();
            var xmlWriter = new XmlTextWriter(writer);
            xmlWriter.Formatting = Formatting.Indented;
            xdoc.WriteTo(xmlWriter);
            richTextBoxTransformed.Text = writer.GetStringBuilder().ToString();

【问题讨论】:

为什么不使用 XDocument 类中的 Remove 方法? XDocument .Remove() 删除一个节点。我需要删除一个属性。 【参考方案1】:

就像 Marc Gravell 在我发布之前指出的那样,xmlns 属性(不合格)本身并不是一个属性,它被认为是元素名称的一部分。

<StackPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    <LinearLayout xmlns="clr-namespace:AndroidAssembly;assembly=AndroidAssembly" />
    <TextView xmlns="clr-namespace:AndroidAssembly;assembly=AndroidAssembly" />
</StackPanel>   

StackPanel 标签在这里没有属性。然而,它的名字是http://schemas.microsoft.com/winfx/2006/xaml/presentationStackPanel

Name.Namespacehttp://schemas.microsoft.com/winfx/2006/xaml/presentationXNamespace 类型)和Name.LocalName == "StackPanel"

因此,您需要有效地重命名元素。它应该可以工作。

过度简化(但可编译)的程序:

using System;
using System.Linq;
using System.Xml.Linq;

namespace ConsoleApplication

    class Program
              
        static void Main(string[] args)
        
            var raw = @"<Window xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
            xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
      <StackPanel>
        <LinearLayout xmlns=""clr-namespace:AndroidAssembly;assembly=AndroidAssembly""/>                
        <TextView xmlns=""clr-namespace:AndroidAssembly;assembly=AndroidAssembly""/>    
  </StackPanel>
</Window>";

            var xml = XElement.Parse(raw);
            var descendants = xml.Descendants().ToArray();
            var stackPanel = descendants.First();
            Console.WriteLine(stackPanel.ToString());

            Console.WriteLine("==================================");
            stackPanel.Name = stackPanel.Name.LocalName; // stripping the namespace off
            Console.WriteLine(stackPanel.ToString());

            Console.ReadLine();
        
    

输出:

<StackPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <LinearLayout xmlns="clr-namespace:AndroidAssembly;assembly=AndroidAssembly" />
  <TextView xmlns="clr-namespace:AndroidAssembly;assembly=AndroidAssembly" />
</StackPanel>
==================================
<StackPanel>
  <LinearLayout xmlns="clr-namespace:AndroidAssembly;assembly=AndroidAssembly" />
  <TextView xmlns="clr-namespace:AndroidAssembly;assembly=AndroidAssembly" />
</StackPanel>

StackPanel 元素的区别很容易注意到...

顺便说一句,您发布的 XML 中有一个错字(TextView 标签未关闭),但我无法编辑它 - 编辑必须至少有 6 个字符长 :)(为什么是 6 个?)

【讨论】:

是的,我明白了。谢谢你。我将使用这种方法。 @Peter17 很高兴我能提供帮助 - 如果它解决了您的问题,请将我的回答标记为已接受【参考方案2】:

xmlns不仅仅是一个属性;它定义类型。 Window 不仅仅是一个名为 Windows 的元素,它具有属性 xmlns 和一个值;相反:Window 是一个名为 Window 的元素在“http://schemas.microsoft.com/winfx/2006/xaml/presentation”命名空间中。您可以尝试简单地更改命名空间,但我不认为这是合法的(我希望 XName 是不可变的)。

aka:您将需要以不同的方式处理此问题。

【讨论】:

谢谢。我会尝试别的。

以上是关于使用 LINQ to XML 删除属性不会持续存在的主要内容,如果未能解决你的问题,请参考以下文章

使用 linq to xml 从 xml 文档中删除 xmlns="something"

C# Linq to XML 读取多个带有属性的标签

C# LINQ-to-XML 选择子元素属性最大的元素

Linq to Xml:删除命名空间

C# Linq to XML 检查元素是不是存在

Linq to XML的基本操作