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><![CDATA[caption <a href="">text</a>]]></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 => f.Parent).Remove()
修改你的方法
对,错过了“整个节点”的提及。感谢提及。
现在您正在删除所有具有文件名的节点,而不是检查它是否与他正在寻找的文件名匹配。如果您不介意,如果您感到困惑,我可以编辑您的答案。
清理了代码,因此未来的查看者不必使用滚动条来查看代码。好答案!
@ChuckSavage 是的,我更喜欢你的编辑。很干净。希望这篇文章能帮助其他尝试做类似功能的人;具有多种工作解决方案和选项。【参考方案2】:
您尝试#1 的问题是您试图将IEnumerable<XElement>
与您的读者值进行比较,这应该有效(假设每个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 的内容:<xml />
。
【讨论】:
我遇到了问题。它没有对 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 节点的主要内容,如果未能解决你的问题,请参考以下文章