解析XML文件时,使用带有IEnumerable <xelement>的Except()</xelement>

时间:2014-05-09 20:26:17

标签: c# xpath ienumerable xelement except

我遇到了C#问题,试图过滤XML文件的内容。

我希望从XML条目列表中删除项目,具体取决于这些项目是否与第二个XML条目列表中找到的项目匹配,并将该筛选后的列表作为新的条目列表返回,我可以迭代并执行操作用。

我正在尝试使用.Except()函数执行此操作,因为它似乎是为此目的而量身定做的。 MSDN上给出的示例似乎表明这正是该函数的用途。

然而它不起作用,我找不到一个优雅的解决方案。我知道每次尝试对其中一个项目进行操作时,我都可以手动遍历第二个列表,但这样做不够优雅,使代码难以阅读。

以下是我的代码无法正常工作的简化示例。

首先,一个示例XML文件:

<?xml version="1.0" encoding="utf-8"?>
<MyTest version="1.0">
  <Validation>
    <Manifest>

      <VerifyItems SinceVersion="1.5">
        <Item Type="File"      Uninstalled="True"  Location="%ProgramData%\MyData"  >MyFirstFile.dat</Item>
        <Item Type="File"      Uninstalled="True"  Location="%ProgramData%\MyData"  >MySecondFile.dat</Item>
        <Item Type="Folder"    Uninstalled="True"  Location="%ProgramData%\MyData"  >MyFirstFolder</Item>
        <Item Type="Folder"    Uninstalled="True"  Location="%ProgramData%\MyData"  >MySecondFolder</Item>
      </VerifyItems>

      <VerifyItems SinceVersion="2.1">
        <Item Type="File"      Uninstalled="True"  Location="%ProgramData%\MyData"  >aNewerFile.dat</Item>
        <Item Type="Folder"    Uninstalled="True"  Location="%ProgramData%\MyData"  >aNewerFolder</Item>
      </VerifyItems>

      <RemovedItems  SinceVersion="2.1">
        <Item Type="Folder"    Uninstalled="True"  Location="%ProgramData%\MyData"  >MyFirstFolder</Item>
        <Item Type="Folder"    Uninstalled="True"  Location="%ProgramData%\MyData"  >MySecondFolder</Item>
      </RemovedItems>

    </Manifest>
  </Validation>
</MyTest>

以下是我想要使用但不起作用的C#代码示例:

// Among other Using statements, I have these up at the top.
using System.Xml.Linq;
using System.Xml.XPath;

// Load the XML file into memory.
XElement XMLFileContents = XElement.Load("MyXMLFile");

// The following statement retrieves all "Verify" items for all versions,
// since the product version cited in the query is newer than everything
// in the file. Total of 6 items.
IEnumerable<XElement> PresentItemResults = XMLFileContents.XPathSelectElements("//VerifyItems[@SinceVersion<=2.20]/Item");

// The following statement retrieves all "Removed" items for all versions,
// total of 2 items. These items both match items already extant in the
// "Verify" list.
IEnumerable<XElement> RemovedItemResults = XMLFileContents.XPathSelectElements("//RemovedItems[@SinceVersion<=2.20]/Item");

// Attempt to create a third list which, in theory, should be only four
// items long, filtering out the two items in the "Removed" list from
// the six items in the "Verify" list. It looks like the "Except()" function
// should do what I want.
IEnumerable<XElement> FilteredItemResults = PresentItemResults.Except(RemovedItemResults);

// However it does not remove the items. The output from below
// is 6 2 6, not 6 2 4 like I'd hoped.
Console.WriteLine(PresentItemResults.Count().ToString());
Console.WriteLine(RemovedItemResults.Count().ToString());
Console.WriteLine(FilteredItemResults.Count().ToString());

// I want to put code here that works with the contents of FilteredItemResults.
// However I am not getting a filtered list.

我怀疑它可能不起作用,因为第二个列表中的元素与第一个列表中的元素具有不同的父元素和兄弟元素,因此,相等函数认为它们不同,因为它的技术性很小。

但我不关心父母和兄弟姐妹,我只想根据每个项目的属性和值从另一个列表中筛选出一个列表。当我对这些项目采取行动时,我只关心属性和值,而不是我从XML树中获取它们的位置。

任何人都可以帮我弄清楚如何以简单而优雅的方式完成这项工作吗?

1 个答案:

答案 0 :(得分:1)

  

但我不关心父母和兄弟姐妹,我只想根据每个项目的属性和价值从另一个列表中筛选出一个列表......

您应该可以拨打IEqualityComparer<> {{1}}来告诉它。