按后代元素的属性过滤XElements

时间:2011-03-15 07:05:00

标签: .net xml linq linq-to-xml

我正在尝试根据该元素的子元素的属性选择元素。

原创Xml:

<Root>
      <Element1 id="1">
        <element2>XXXX</element2>
        <element3>XXXX</element3>
        <element4>XXXX</element4>
        <Filter attr1="1" attr2="0" attr3="0" attr4="1" attr5="0"></Filter>
      </Element1>
      <Element1 id="2">
        <element2>XXXX</element2>
        <element3>XXXX</element3>
        <element4>XXXX</element4>
        <Filter attr1="1" attr2="0" attr3="1" attr4="1" attr5="0"></Filter>
      </Element1>
      <Element1 id="3">
        <element2>XXXX</element2>
        <element3>XXXX</element3>
        <element4>XXXX</element4>
        <Filter attr1="1" attr2="1" attr3="0" attr4="1" attr5="0"></Filter>
      </Element1>
    </Root>

这是我到目前为止所做的:

Dim xmlElement = (From rec In RecipeXmlDocument.Descendants("Element1") _
Where (rec.Descendants("Filter").@attr1= "1" _
                   Or rec.Descendants("Filter").@attr2 = "0" _
                   Or rec.Descendants("Filter").@attr3 = "0" _
                   And (rec.Descendants("Filter").@attr4 = "1" _
                        Or rec.Descendants("Filter").@attr5 = "0" _

这会抛出以下错误:“抛出了类型'System.Linq.SystemCore_EnumerableDebugViewEmptyException'的异常。”

代码尝试做的是选择所有Element1,其中该element1的filter元素与该语句的where子句匹配。

我对linq很新,我不确定我做错了什么。

2 个答案:

答案 0 :(得分:0)

我认为你应该朝着这个方向前进:

RecipeXmlDocument.Root.Elements()
.Where(e => e.Elements("Filter").SingleOrDefault( [filter conditions] ) != null);

这将获取root下的所有元素,其中名为“Filter”的单个子元素与[filter conditions]匹配。如果不存在这样的子元素,SingleOfDefault将返回null,因此Where子句为false,并且不包含该元素。

根据你的情况,你可能需要稍微调整一下。

[过滤条件]可能类似于:

f => f.Attribute("attr1").Value == "1" && f.Attribute("attr2").Value == "2"

更新:我尝试将其转换为VB.net(手指交叉):

Dim xmlElement = 
 (From rec In RecipeXmlDocument.Descendants("Element1") _
 Where not (From filter in rec.Elements("Filter").Any( _
 Function(f) f.Attribute("attr1") = "1" And f.Attribute("attr2") = "2") is Nothing)

很有可能这不会编译,你需要做出调整,但我希望它有所帮助:)

答案 1 :(得分:0)

在这种情况下,XPath可能会产生正确的结果而工作量少于LINQ。您可以制定一个XPath查询,如:

/Root/Element1[Filter[(@attr1 = '1' or @attr2 = '0' or @attr3 = '0')
                  and (@attr4 = '1' or @attr5 = '0')]]

(我在与or结合的测试中添加了括号,因为我怀疑这是你想要的,但我可能是错的。)这将找到所有Element1元素Filter子元素,其属性传递描述的谓词。

然后,您可以使用XDocument.XPathSelectElements()

迭代这些元素
var elements = doc.XPathSelectElements(xpath);