我有以下xml文件
- <annotations>
- <annotation value="Black and white, outdoor" eventID="1">
<image location="0928262.JPG" />
</annotation>
- <annotation value="CLear, obstacles" eventID="2">
<image location="0928262.JPG" />
</annotation>
</annotations>
我有一个接收文件位置的函数,然后从xml文件中删除它,就像这样,
private void remEntry(String fName)
{
string xmlFile = path + "\\output.xml";
if (File.Exists(xmlFile))
{
XDocument xdoc = XDocument.Load(xmlFile);
foreach (var x in xdoc.Descendants("annotation").ToList())
{
foreach (var el in xdoc.Descendants("image").ToList())
{
if (el.Attribute("location").Value == fName)
{
el.Remove();
}
}
}
xdoc.Save(xmlFile);
}
}
这样可行,但我遇到了问题,此代码将从xml文件中删除所有文件名实例,我只想删除与特定eventID绑定的文件名。事件ID在文本窗口中显示在应用程序中。所以,我在循环中添加了以下内容
foreach (var x in xdoc.Descendants("annotation").ToList())
{
foreach (var el in xdoc.Descendants("image").ToList())
{
if (el.Attribute("location").Value == fName &&
x.Attribute("eventID").Value == eventID.Text)
{
el.Remove();
}
}
这里的想法是,如果图像名称等于输入,并且图像的eventID与显示的EventID相同,则删除该元素。但它仍然会删除文件名的所有实例。
这是预期的结果,其中eventID = 2。
- <annotations>
- <annotation value="Black and white, outdoor
<image location="0928262.JPG" />
</annotation>
- <annotation value="CLear, obstacles" eventID="2">
</annotation>
</annotations>
这是我得到的,
- <annotations>
- <annotation value="Black and white, outdoor" eventID="1">
</annotation>
- <annotation value="CLear, obstacles" eventID="2">
</annotation>
</annotations>
答案 0 :(得分:3)
将您的方法更改为以下内容,它将起作用
foreach (var x in xdoc.Descendants("annotation").ToList())
{
foreach (var el in x.Descendants("image").ToList())
{
if (el.Attribute("location").Value == loc && x.Attribute("eventID").Value == id)
{
el.Remove();
}
}
}
第二个foreach需要获得第一个foreach提供的当前元素的后代。
您的代码始终从完整文档中获取后代,这导致当第一个foreach遇到带有eventID == 2
的元素时,它将从完整文档中删除具有指定位置的所有图像。
答案 1 :(得分:2)
您可以使用XPath查询,而不是使用嵌入式 foreach 循环来查找要删除的节点。为此,首先必须导入 System.Xml.XPath 命名空间:
using System.Xml.XPath;
然后使用以下代码:
var id = 1;
var fileName = "0928262.JPG";
foreach (var x in xdoc.XPathSelectElements(String.Format(@"//annotation[@eventID={0}]/image[@location=""{1}""]", id, fileName)))
{
x.Remove();
}
答案 2 :(得分:1)
我认为在内部foreach循环中你有xdoc.descendents(),它给你们两个图像元素。尝试使用x.Descendents() -
foreach (var el in x.Descendants("image").ToList())
答案 3 :(得分:1)
。似乎你的循环嵌套是不正确的。最初,您循环遍历文档中的所有注释:
foreach (var x in xdoc.Descendants("annotation").ToList())
并且您循环遍历文档中的所有图片:foreach (var el in xdoc.Descendants("image").ToList())
如果你要打印位置和eventID,你会得到这个:
正如您在此输出中所看到的,您将符合删除条目两次的条件。
你应该做的是:
foreach (var x in xdoc.Descendants("annotation").ToList())
{
foreach (var el in x.Descendants("image").ToList())
{
if (el.Attribute("location").Value == fName &&
x.Attribute("eventID").Value == eventID.Text)
{
el.Remove();
}
}
}