开发者

Remove attributes from XElement

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 do开发者_如何学JAVAcument is still the same. If somebody had similar problem, please help me.


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.


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);
    }
}


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;
    }


 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();
                }
            }


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜