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

时间:2012-08-10 10:27:35

标签: .net xml linq xml-parsing linq-to-xml

我有以下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();

2 个答案:

答案 0 :(得分:3)

就像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/presentation}StackPanel

Name.Namespace{http://schemas.microsoft.com/winfx/2006/xaml/presentation}XNamespace类型)和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 ?)

答案 1 :(得分:2)

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

又名:你需要以不同的方式解决这个问题。