【问题标题】:How do I remove empty tags in C# after innerXML has been removed?删除 innerXML 后,如何删除 C# 中的空标签?
【发布时间】:2019-04-15 20:37:23
【问题描述】:

当用户在我的 DataGrid 中选择一行并单击删除时,我想从我的文档中删除节点。

我的结果显示只有内部 XML 已被删除,但标签仍留在我的文档中。

有什么想法吗?

我也试过了:

n.ParentNode.ChildNodes.Remove(n);
        public void Delete_Click(object sender, RoutedEventArgs e)
        {
            JobList selected = (JobList)DG.SelectedItem;
            MessageBox.Show("ROW WITH ID : " + selected.Job + " HAS BEEN SELECTED.");
            DG.Items.Remove(selected);
            DeleteXmlNode(@"C:\Users\contract_lshamoon\Desktop\arm\arm\arm\xmldb.xml", "Job", selected.Job);
        }
        private static void DeleteXmlNode(string path, string tagname, string searchconditionAttributevalue)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(path);
            XmlNodeList nodes = doc.GetElementsByTagName(tagname);
            AddFileSecurity(path, FileSystemRights.ReadData, AccessControlType.Allow);
            XmlNode root = doc.DocumentElement;

            foreach (XmlNode n in root)
            {
                Console.WriteLine(n.Name);
                if (n.Attributes["JobId"].Value == searchconditionAttributevalue)
                {
                    n.RemoveAll();
                }
            }
            doc.Save(path);
        }
<?xml version="1.0" encoding="utf-8"?>
<Jobs>
  <Job>
  </Job>
  <Job JobId="d7bf1b4e-a452-4417-aa72-2ba23c246fc3">
    <JobDate>04/09/2019 2:21 PM</JobDate>
    <File>C:\Users\contract_lshamoon\Desktop\filedeleter\index - Copy.js</File>
    <FilePath>C:\Users\contract_lshamoon\Desktop\filedeleter</FilePath>
    <Extension>js</Extension>
    <Age>1</Age>
    <JobComment>Deleted : 62 files.</JobComment>
  </Job>
  <Job JobId="997dd4cd-b29f-4de4-ad0f-4d4d72a5fe28">
    <JobDate>04/09/2019 2:21 PM</JobDate>
    <File>C:\Users\contract_lshamoon\Desktop\filedeleter\index.js</File>
    <FilePath>C:\Users\contract_lshamoon\Desktop\filedeleter</FilePath>
    <Extension>js</Extension>
    <Age>1</Age>
    <JobComment>Deleted : 55 files.</JobComment>
  </Job>
</Jobs>

【问题讨论】:

    标签: c# xml attributes xmlnode


    【解决方案1】:

    你可以试试n.ParentNode.RemoveChild(n); 代替n.RemoveAll();

    您必须通过 XmlNodeList,而不是通过 XmlNode。下面我在Rextester中测试了你的数据,你可以自己试试:

    //Rextester.Program.Main is the entry point for your code. Don't change it.
    //Compiler version 4.0.30319.17929 for Microsoft (R) .NET Framework 4.5
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text.RegularExpressions;
    using System.Xml;
    
    namespace Rextester
    {
    public class Program
    {
        public static void Main(string[] args)
        {
            String str = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" + 
        "<Jobs>\r\n" + 
        "  <Job>\r\n" + 
        "  </Job>\r\n" + 
        "  <Job JobId=\"d7bf1b4e-a452-4417-aa72-2ba23c246fc3\">\r\n" + 
        "    <JobDate>04/09/2019 2:21 PM</JobDate>\r\n" + 
        "    <File>C:\\Users\\contract_lshamoon\\Desktop\\filedeleter\\index - Copy.js</File>\r\n" + 
        "    <FilePath>C:\\Users\\contract_lshamoon\\Desktop\\filedeleter</FilePath>\r\n" + 
        "    <Extension>js</Extension>\r\n" + 
        "    <Age>1</Age>\r\n" + 
        "    <JobComment>Deleted : 62 files.</JobComment>\r\n" + 
        "  </Job>\r\n" + 
        "  <Job JobId=\"997dd4cd-b29f-4de4-ad0f-4d4d72a5fe28\">\r\n" + 
        "    <JobDate>04/09/2019 2:21 PM</JobDate>\r\n" + 
        "    <File>C:\\Users\\contract_lshamoon\\Desktop\\filedeleter\\index.js</File>\r\n" + 
        "    <FilePath>C:\\Users\\contract_lshamoon\\Desktop\\filedeleter</FilePath>\r\n" + 
        "    <Extension>js</Extension>\r\n" + 
        "    <Age>1</Age>\r\n" + 
        "    <JobComment>Deleted : 55 files.</JobComment>\r\n" + 
        "  </Job>\r\n" + 
        "</Jobs>";
    
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(str);
            XmlNodeList nodes = doc.SelectSingleNode("Jobs").SelectNodes("Job");
            for (int i = nodes.Count - 1; i >= 0; i--)
            {
                 if (nodes[i].Attributes["JobId"] == null) //this statement removes null tags
                 {
                     nodes[i].ParentNode.RemoveChild(nodes[i]);
                 } else if(nodes[i].Attributes["JobId"].Value == "d7bf1b4e-a452-4417-aa72-2ba23c246fc3") //this statement removes selected tag.
                    nodes[i].ParentNode.RemoveChild(nodes[i]);
            }        
            Console.WriteLine(doc.OuterXml);
        }
      }
    }
    

    编辑DeleteXmlNode方法:

    private static void DeleteXmlNode(string path, string tagname, string searchconditionAttributevalue)
    {
        XmlDocument doc = new XmlDocument();
        doc.Load(path);
        XmlNodeList nodes = doc.GetElementsByTagName(tagname);
        AddFileSecurity(path, FileSystemRights.ReadData, AccessControlType.Allow);
    
        XmlNodeList nodes = doc.SelectSingleNode("Jobs").SelectNodes("Job");
        for (int i = nodes.Count - 1; i >= 0; i--)
        {
             if (nodes[i].Attributes["JobId"] == null) //this statement removes null tags
             {
                 nodes[i].ParentNode.RemoveChild(nodes[i]);
             } else if(nodes[i].Attributes["JobId"].Value == searchconditionAttributevalue) //this statement removes selected tag.
                nodes[i].ParentNode.RemoveChild(nodes[i]);
        }   
    
        doc.Save(path);
    }
    

    【讨论】:

    • 这可行,但我需要从文件中读取 XML,而不是字符串。
    • 您知道我发布此示例以显示代码正在运行。在您的代码中,您只需更改相关部分。顺便说一句,我做了一个版本来回答,所以你可以直接使用它
    • 感谢您的帮助!
    • 您的示例有效,但问题是:我没有像我说的那样从数组中读取文本。我正在从我的项目中的单独 xml 文件中读取 xml
    【解决方案2】:

    感谢大家的回答。 这是对我有用的解决方案: 它通过从根中删除一个子节点来工作。

    private static void DeleteXmlNode(string path, string tagname, string searchVal)
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(path);
                XmlNodeList nodes = doc.GetElementsByTagName(tagname);
                XmlNode root = doc.DocumentElement;
                foreach (XmlNode n in root)
                {
                    if (n.Attributes["Id"].Value == searchVal)
                    {
                        root.RemoveChild(n);
                    }
                }
                using (var tw = new StreamWriter(@"~../../../../Log/Log.txt".Trim(), true))
                {
                    tw.WriteLine(DateTime.Now + "\t" + WinId + "\t DELETED Job ::: " + searchVal);
                }
                doc.Save(path);
            }
    

    【讨论】: