3 尝试使用 C# 删除 XML 节点

Posted

技术标签:

【中文标题】3 尝试使用 C# 删除 XML 节点【英文标题】:3 Attempts to delete XML node using C# 【发布时间】:2013-12-31 04:27:28 【问题描述】:

我尝试了 3 种不同的方式从我的 XML 文件中删除一个节点;每一条路我都是空的。我正在查询 SQL 数据库并获取文件名,如果 XML 文档中的文件名 = SQL 数据库结果,我想删除整个节点。

我不确定我的代码有什么问题:

背景资料

fn44 是从 SQL 数据库中获取的文件名(我的所有信息都在 SQL 表,我需要一个用于 javascript 的 XML 文件)

XML:

<?xml version="1.0" encoding="utf-8"?>
<xml>
  <bannerMain>
    <department>main</department>
    <filename>resdrop.png</filename>
    <title>This is a Title</title>
    <text>&lt;![CDATA[caption <a href="">text</a>]]&gt;</text>
  </bannerMain>
</xml>

尝试 1(我知道我没有正确找到孩子,似乎无法弄清楚如何解决它):

XDocument doc = XDocument.Load(Server.MapPath("~/uploads/banners.xml"));
var q = from node in doc.Descendants("bannerMain")
        let fina = node.Descendants("filename")/*PROBLEM LINE*/
        where fina != null && fina == myReader[0]/*Gets filename from SQL database*/
select node;
q.ToList().ForEach(x => x.Remove());
doc.Save(Server.MapPath("~/uploads/banners.xml"));

尝试 2(应该在我的脑海中起作用,但没有)

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(Server.MapPath("~/uploads/banners.xml"));
XmlNode nodeToDelete = xmlDoc.SelectSingleNode("/xml/bannerMain[@filename=" 
+ fn44 + "]");
if (nodeToDelete != null)

   nodeToDelete.ParentNode.RemoveChild(nodeToDelete);

xmlDoc.Save(Server.MapPath("~/uploads/banners.xml"));

尝试 3(类似于尝试 2)

string nodeToDelete = fn44;
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(Server.MapPath("~/uploads/banners.xml"));
XmlNode node = xmlDoc.SelectSingleNode(string.Format("//*[filename=\"0\"]"
, nodeToDelete));
if (node != null)
   xmlDoc.SelectSingleNode("xml/bannersMain").RemoveChild(node);
xmlDoc.Save(Server.MapPath("~/uploads/banners.xml"));

我想将文件名 = 的整个节点删除为从 SQL 数据库中获取的文件名。非常感谢任何帮助/资源。

已解决: 以下答案中有几个不同的选项效果很好。

解决方案 1:

var xDoc = XDocument.Load(Server.MapPath("~/uploads/banners.xml"));
string fileName = fn44; //Use whatever value you found in SQL DB...

xDoc.Descendants("filename").Where(c => c.Value == fileName).Select(x => x.Parent).Remove();
xDoc.Save(Server.MapPath("~/uploads/banners.xml"));

解决方案 2:

XDocument doc = XDocument.Load(Server.MapPath("~/uploads/banners.xml"));
var q = from node in doc.Descendants("bannerMain")
        let fina = node.Element("filename")
        where fina != null && fina.Value == fn44
        select node;
q.Remove();
doc.Save(Server.MapPath("~/uploads/banners.xml"));

【问题讨论】:

为什么不从一个没有文件名的 XML 模板开始,然后添加所有文件名,除了在数据库中找到的文件名之外的所有文件名?这有意义吗? xml节点是在新文件的上传过程中创建的。此时会生成 SQL 和 XML 信息。当我尝试删除条目时,我正在运行这个过程。从而从服务器、xml 文档以及 SQL 数据库中删除文件。我有服务器和 SQL 删除工作; xml 删除被证明是困难的。 【参考方案1】:

这似乎对我有用:

        string xmlfile = Server.MapPath("~/uploads/banners.xml");
        var xDoc = XDocument.Load(xmlfile);
        string fileName = "resdrop.png"; // Value from SQL DB

        xDoc.Descendants("filename")
            .Where(c => c.Value == fileName)
            .Select(x => x.Parent)
            .Remove();
        xDoc.Save(xmlfile);

【讨论】:

如果您查看他的代码 Francis,您会看到他不想删除所有文件名节点,而是删除父横幅节点,其中它有一个与他的搜索匹配的子文件名。我会用.Select(f =&gt; f.Parent).Remove() 修改你的方法 对,错过了“整个节点”的提及。感谢提及。 现在您正在删除所有具有文件名的节点,而不是检查它是否与他正在寻找的文件名匹配。如果您不介意,如果您感到困惑,我可以编辑您的答案。 清理了代码,因此未来的查看者不必使用滚动条来查看代码。好答案! @ChuckSavage 是的,我更喜欢你的编辑。很干净。希望这篇文章能帮助其他尝试做类似功能的人;具有多种工作解决方案和选项。【参考方案2】:

您尝试#1 的问题是您试图将IEnumerable&lt;XElement&gt; 与您的读者值进行比较,这应该有效(假设每个bannerMain 只有一个filename 元素):

var q = from node in doc.Descendants("bannerMain") 
        let fina = node.Element("filename")//only single filename, so get just that XElement
        where fina != null && fina.Value == reader[0]//assumes reader[0] is a string value
        select node;

要删除它们,只需这样做:

q.Remove();
doc.Save(Server.MapPath("~/uploads/banners.xml"));

我通过 LINQPad 运行了这个,在执行q.Remove(); 之后,这里是 doc 的内容:&lt;xml /&gt;

【讨论】:

我遇到了问题。它没有对 xml 文件进行任何更改。 谢谢!我认为这可能是问题所在,打算再试一次! 好吧,它仍然不存在...对于 doc.Descendants("bannerMain"),我是否需要导航到“xml/bannerMain”。 xml 是无所不包的 xml 持有者。 (查看上面的 XML 示例) 不,后代不需要任何路径,它会在整个 Xml 中查找。我使用您发布的 xml sn-p 对此进行了测试,并且效果很好。您的示例 Xml 和真实的 Xml 之间是否存在结构差异? 嗯,不,完全一样。【参考方案3】:

这有点冗长,但这里是一个非 linq sn-p:

void DeleteNode(string fileName)

    XmlDocument doc = new XmlDocument();
    doc.Load(Server.MapPath("~/uploads/banners.xml"));

    //Get all the bannerMain nodes.
    XmlNodeList nodelist = doc.SelectNodes("/xml//bannerMain");

    if (nodelist != null)
    
        foreach (XmlNode node in nodelist)
        
            //Look for then filename child. If it contains desired value
            //delete the entire bannerMain node. Assumes order of child nodes
            //may not be a constant.
            foreach (XmlNode child in node.ChildNodes)
            
                if (child.Name == "filename" && child.InnerText == name)
                
                    node.ParentNode.RemoveChild(node);
                
            
        

        doc.Save(Server.MapPath("~/uploads/banners.xml"));
    

【讨论】:

(只是为了澄清我的理解)您设置为变量的字符串'fileName';那是我将从 SQL 数据库中获取和设置的变量正确吗?? 是的。你可以传入任何你想查找和删除的文件名。 感谢您的澄清【参考方案4】:

对于尝试 #2,删除文件名的 @ 符号。 @ 符号代表一个属性,但文件名是一个子节点。

如果你的短语不起作用,我会改写一下:

"/xml/bannerMain[文件名=

"//bannerMain[文件名=

【讨论】:

我没有意识到 @ 符号与属性相关。感谢您澄清这一点。我将尝试进行编辑,看看它是否解决了这个选项的问题。

以上是关于3 尝试使用 C# 删除 XML 节点的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 C# 从 XML 节点列表中删除节点

如何使用 vbscript 删除 XML 文件中的特定节点

使用 TSQL 从 XML 中删除具有特定值的节点

如何从xml中删除列表父节点?

(急)c#中datagridview表中删除行后重新加载后删除的行会变成空白行。数据是没有了,空白行是啥情况?

xml查找节点父节点并删除simplexml php