Фильтрация элементов XE по атрибутам дочернего элемента - PullRequest
1 голос
/ 15 марта 2011

Я пытаюсь выбрать элементы на основе атрибутов субэлемента этого элемента.

Оригинальный 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, в которых элемент фильтра этого элемента1 соответствует предложению where оператора.

Я довольно новичок в linq, и я не совсем уверен, что я делаю неправильно.

Ответы [ 2 ]

0 голосов
/ 16 марта 2011

Это тот случай, когда 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);
0 голосов
/ 15 марта 2011

Я думаю, что вы должны идти в этом направлении:

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

Это берет все элементы под корнем, где один подэлемент с именем "Filter" соответствует [условиям фильтра].Если такого подэлемента не существует, SingleOfDefault вернет null и, следовательно, предложение Where будет ложным, а элемент не будет включен.

Возможно, вам придется немного подстроить его в соответствии ск вашему случаю.

[условия фильтра] могут выглядеть примерно так:

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)

Скорее всего, это не скомпилируется, и вам нужно внести изменения, но я надеюсь, что это поможет:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...