Remove attributes from XElement

风格不统一 提交于 2020-01-03 23:16:15

问题


I am trying to remove some attributes from xml document. Here is what I tried:

private void RemoveEmptyNamespace(XElement element) {
            foreach (XElement el in element.Elements()) {
                if (el.Attribute("xmlns") != null && el.Attribute("xmlns").Value == string.Empty)
                    el.Attribute("xmlns").Remove();
                if (el.HasElements)
                    RemoveEmptyNamespace(el);
            }
        }

But it doesn't work. When I debug inside the method, attribute is removed, but when the method is fully executed, no changes were saved. The document is the same. I suppose that is because of foreach loop, but I don't see other way of looping through.

Any suggestions are appreciated.

EDIT: Here is the whole code I am using:

        var file = new FileStream(destinationPath, FileMode.Open);
        var doc = new XDocument();
        doc = XDocument.Load(savedFile);
        RemoveEmptyNamespace(doc.Root);//method above
        file.SetLength(0);
        doc.Save(file);
        file.Close();

EDIT2: Now I have tried to achieve the same goal by going line by line and replacing strings. And nothing happens!!! The document is still the same. If somebody had similar problem, please help me.


回答1:


I have found what the actual problem was. XDocument class was adding blank xmlns every time I changed something in the document! That is why I couldn't remove them. It behaves like that because it needs namespace definition for every XElement you create. So I solved the problem by doing so. The only thing that needs to be done is adding namespace to the XElement name. Something like this:

XNamespace nameSpace = "http://schemas.microsoft.com/developer/msbuild/2003";
var subType = new XElement(nameSpace + "SubType"); // strange but true

I hope this will help someone with the same problem. Thanks everybody for your answers.




回答2:


This work for me:

private static void RemoveEmptyNamespace(XElement element)
{
    XAttribute attr = element.Attribute("xmlns");
    if (attr != null && string.IsNullOrEmpty(attr.Value))
        attr.Remove();
    foreach (XElement el in element.Elements())
        RemoveEmptyNamespace(el);
}

Only difference is that i'm counting with xmlns attribute in root element too. But it really works, trust me

whole test:

class Program
{
    static void Main(string[] args)
    {
        var x = new XElement("root", new XElement("t", new XAttribute("xmlns", "")), new XAttribute("aaab", "bb"));
        Console.WriteLine(x);
        RemoveEmptyNamespace(x);
        Console.WriteLine(x);
    }

    private static void RemoveEmptyNamespace(XElement element)
    {
        XAttribute attr = element.Attribute("xmlns");
        if (attr != null && string.IsNullOrEmpty(attr.Value))
            attr.Remove();
        foreach (XElement el in element.Elements())
            RemoveEmptyNamespace(el);
    }
}



回答3:


return the XElement from method and assign back it to variable, or pass as reference

private XElement RemoveEmptyNamespace(XElement element) {
        foreach (XElement el in element.Elements()) {
            if (el.Attribute("xmlns") != null && el.Attribute("xmlns").Value == string.Empty)
                el.Attribute("xmlns").Remove();
            if (el.HasElements)
                el = RemoveEmptyNamespace(el);
        }
      return element;
    }



回答4:


 string xml = File.ReadAllText(@"C:\xml.txt");
            XDocument wapProvisioningDoc = XDocument.Parse(xml);
            foreach(var ele in wapProvisioningDoc.Elements().Elements("characteristic"))//characteristic
            {
                var attribute = ele.Attribute("target");
                if (attribute != null && !string.IsNullOrEmpty(attribute.Value))
                {
                    attribute.Remove();
                }
            }



回答5:


The problem is that you are deleting the attribute from a read-only object created in the "foreach" loop. You must delete the instance child from "elements", not from "el".

I think a better and easy option is the use of a "for" for this task. in C# maybe something like that:

for (int i = 0; i < element.ChildNodes.Count; i++)
        {
            if (element.ChildNodes[i].Attributes["xmlns"] != null && element.ChildNodes[i].Attributes["xmlns"].Value == String.Empty)
            {
                element.ChildNodes[i].Attributes.RemoveNamedItem("xmlns");
            }
            if (element.ChildNodes[i].HasChildNodes)
            {
                element.ChildNodes[i].RemoveAll();
            }
        }

Hope this helps.

EDIT: don't create a new object, create a read-only object but it references to interation object.



来源:https://stackoverflow.com/questions/6593243/remove-attributes-from-xelement

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!