Удалить атрибуты из XElement - PullRequest
3 голосов
/ 06 июля 2011

Я пытаюсь удалить некоторые атрибуты из XML-документа.Вот что я попробовал:

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

Но это не работает.Когда я выполняю отладку внутри метода, атрибут удаляется, но когда метод выполняется полностью, изменения не сохраняются.Документ такой же.Я полагаю, что это из-за цикла foreach, но я не вижу другого пути прохождения цикла.

Любые предложения приветствуются.

РЕДАКТИРОВАТЬ: Вот весь код, который я использую:

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

РЕДАКТИРОВАТЬ2: Теперь я попытался достичь той же цели, перейдяпострочно и заменяя строки.И ничего не происходит !!!Документ все тот же.Если у кого-то была подобная проблема, пожалуйста, помогите мне.

Ответы [ 5 ]

9 голосов
/ 06 июля 2011

Я нашел, в чем была проблема.Класс XDocument добавлял пустые xmlns каждый раз, когда я что-то изменял в документе!Вот почему я не мог их удалить.Он ведет себя так, потому что для каждого создаваемого вами XElement требуется определение пространства имен.Так что я решил проблему, сделав это.Единственное, что нужно сделать, это добавить пространство имен к имени XElement.Примерно так:

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

Надеюсь, это поможет кому-то с такой же проблемой.Спасибо всем за ваши ответы.

6 голосов
/ 06 июля 2011

Эта работа для меня:

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

Разница лишь в том, что я считаю с атрибутом xmlns в корневом элементе тоже.Но это действительно работает, поверь мне

весь тест:

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);
    }
}
0 голосов
/ 18 июня 2018
 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();
                }
            }
0 голосов
/ 06 июля 2011

Проблема в том, что вы удаляете атрибут из объекта только для чтения, созданного в цикле "foreach".Вы должны удалить дочерний экземпляр из «элементов», а не из «el».

Я думаю, что лучшим и простым вариантом является использование «для» для этой задачи.в C # может быть что-то вроде этого:

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

Надеюсь, что это поможет.

РЕДАКТИРОВАТЬ: не создавать новый объект, создать объект только для чтения, но он ссылается на объект Interation.

0 голосов
/ 06 июля 2011

возвращает XElement из метода и присваивает его обратно переменной или передает в качестве ссылки

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