(Первое сообщение, пожалуйста, будьте нежнее!)
Я только изучаю LINQ to XML во всей его красе и хрупкости, пытаясь взломать его, чтобы сделать то, что я хочу:
Имеется такой XML-файл -
<list>
<!-- random data, keys, values, etc.-->
<key>FIRST_WANTED_KEY</key>
<value>FIRST_WANTED_VALUE</value>
<key>SECOND_WANTED_KEY</key>
<value>SECOND_WANTED_VALUE</value> <!-- wanted because it's first -->
<key>SECOND_WANTED_KEY</key>
<value>UNWANTED_VALUE</value> <!-- not wanted because it's second -->
<!-- nonexistent <key>THIRD_WANTED_KEY</key> -->
<!-- nonexistent <value>THIRD_WANTED_VALUE</value> -->
<!-- more stuff-->
</list>
Я хочу извлечь значения набора известных "требуемых ключей" надежным способом, то есть, если SECOND_WANTED_KEY
появляется дважды, я хочу только SECOND_WANTED_VALUE
, а не UNWANTED_VALUE
. Кроме того, THIRD_WANTED_KEY
может появиться или не появиться, поэтому запрос должен быть в состоянии справиться и с этим. Я могу предположить, что FIRST_WANTED_KEY
появится перед другими ключами, но не могу предположить что-либо о порядке других ключей - если ключ появляется дважды, его значения не важны, я хочу только первый. Подходит анонимный тип данных, состоящий из строк.
Моя попытка была сосредоточена вокруг чего-то такого:
var z = from y in x.Descendants()
where y.Value == "FIRST_WANTED_KEY"
select new
{
first_wanted_value = ((XElement)y.NextNode).Value,
//...
}
Мой вопрос: что это должно быть ...
? Я пытался, например, (некрасиво, я знаю)
second_wanted_value = ((XElement)y.ElementsAfterSelf()
.Where(w => w.Value=="SECOND_WANTED_KEY")
.FirstOrDefault().NextNode).Value
, который, как мы надеемся, должен позволять ключу находиться где угодно или вообще не существовать, но это не сработало, поскольку .NextNode
при нулевом XElement
, похоже, не работает.
Я также пытался добавить в
.Select(t => {
if (t==null)
return new XElement("SECOND_WANTED_KEY","");
else return t;
})
предложение после где, но это тоже не сработало.
Я открыт для предложений, (конструктивной) критики, ссылок, ссылок или предложений фраз в Google и т. Д. Я проделал большую работу по поиску в Google и проверке SO, поэтому любая помощь будет принята.
Спасибо!
EDIT:
Позвольте мне добавить слой сложности к этому - я должен был включить это в первую очередь. Допустим, документ XML выглядит так:
<lists>
<list>
<!-- as above -->
</list>
<list>
<!-- as above -->
</list>
</lists>
и я хочу извлечь несколько наборов этих пар ключ-значение. Вопрос / предостережение: если SECOND_WANTED_KEY
не появляется в первом элементе <list>
, но появляется во втором, я не хочу случайно выбрать второй элемент списка SECOND_WANTED_KEY
.
РЕДАКТИРОВАТЬ # 2:
В качестве другой идеи я попытался создать HashSet
ключей, которые я ищу, и делаю это:
HashSet<string> wantedKeys = new HashSet<string>();
wantedKeys.Add("FIRST_WANTED_KEY");
//...add more keys here
var kvp = from a in x.Descendants().Where(a => wantedKeys.Contains(a.Value))
select new KeyValuePair<string,string>(a.value,
((XElement)a.NextNode).Value);
Это дает мне все пары ключ-значение, но я не уверен, гарантирует ли это, что я правильно "свяжу" пары с их родительским элементом `'. Любые мысли или сравнения между этими двумя подходами будут полезны.
Обновление статуса 4/9/10
На данный момент я все еще думаю, что подход с использованием хеш-набора является наиболее предпочтительным. Похоже, что большая часть обработки XML, выполняемая .NET, выполняется в порядке документов - до сих пор все мои тесты были выполнены.
Я бы предложил ответы за вознаграждение и / или голосование, но мне не хватило бы очков за это. Я приму решение сегодня, так что давай! Спасибо.