Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从XML文件中删除特定条目_C#_Xml_Linq To Xml - Fatal编程技术网

C# 从XML文件中删除特定条目

C# 从XML文件中删除特定条目,c#,xml,linq-to-xml,C#,Xml,Linq To Xml,我有以下xml文件 - <annotations> - <annotation value="Black and white, outdoor" eventID="1"> <image location="0928262.JPG" /> </annotation> - <annotation value="CLear, obstacles" eventID="2"> <i

我有以下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文件中删除文件名的所有实例,我只想删除绑定到特定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>
-

-将您的方法更改为以下方法,它将起作用

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的元素时,它将从完整文档中删除指定位置的所有图像。

除了使用嵌入的foreach循环查找要删除的节点,还可以使用XPath查询。为此,首先必须导入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();
}

我认为在内部foreach循环中有xdoc.degents(),它为您提供了两个图像元素。尝试使用x.degents()-


foreach(x.substands(“image”).ToList()中的变量el)
。循环的嵌套似乎不正确。最初,您可以循环查看文档中的所有批注:
foreach(xdoc.substands(“annotation”).ToList()中的变量x)
和您循环文档中所有图像的代码:
foreach(xdoc.substands(“image”).ToList()中的变量el)

如果您要打印位置和eventID,您将得到:

  • eventID 10928262.JPG(第一个位置)
  • eventID 10928262.JPG(第二个位置)
  • eventID 220928262.JPG(第一个位置)
  • eventID 220928262.JPG(第二个位置)
从这个输出中可以看到,您将两次匹配删除条目的条件

您可能应该做的是:

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

在您预期的结果中,Xml的格式似乎不是很好。在任何情况下,当
el.Remove()时,您是否可以通过逐步调试执行代码并检查
x
el
的值行是否执行?这可能会让你走上正轨。(+1表示结构清晰(就问题而言)完整且可理解的问题。)与您的问题无关:您应该从
XDocument.subjects
调用中删除
ToList
<代码>子体
返回一个
IEnumerable
,它允许使用
foreach
循环;无需将其转换为
列表
,该列表使用不必要的循环并创建垃圾。我还将强调代码没有明显的错误。您需要运行调试器并找出问题所在。@Kivin:当调用
el.Remove()
时,集合被更改,这可能会导致可枚举项出现问题。因此,在这种情况下,
ToList()
有其原因。@O.R.Mapper我以前做过,
x
el
都有我期望的值,但问题是由于我从整个文档中删除了它,而不是从当前元素的子体中删除了它。很好,修复了它:)感谢您的解释
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();
}
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();
        }
    }
}