#c# #xml #linq #silverlight-4.0 #linq-to-xml
#c# #xml #linq #silverlight-4.0 #linq-to-xml
Вопрос:
У меня XML точно такого формата:
<?xml version="1.0" encoding="utf-8"?>
<book>
<chapter>
<verse>This is verse 1</verse>
<verse>This is verse 2</verse>
<verse>This is verse 3</verse>
<verse>This is verse 4</verse>
</chapter>
<chapter>
<verse>This is verse 1</verse>
<verse>This is verse 2</verse>
</chapter>
<chapter>
<verse>This is verse 1</verse>
</chapter>
</book>
В C # с использованием Linq мне нужно иметь возможность получать XML-элемент с определенной позицией или индексом на основе значения функции state.getChapterNumber(). Например, если значение равно 4, мне нужно извлечь элемент 4th chapter из XML-документа.
XDocument book = XDocument.Load(string.Format("Translations/NWT/{0}.xml", state.BookName));
var verses = from chapter in book.Decendants()
where state.getChapterNumber() == (WHAT DO I PUT HERE TO MATCH THE VALUE??)
from verse in chapter.Descendants("p").Elements()
select new
{
VerseNumber = verse.Attribute("n").Value,
Text = verse.Value,
LastVerseInParagraph = verse.Parent.Elements().LastOrDefault().Value,
FirstVerseInParagraph = verse.Parent.Elements().FirstOrDefault().Value
};
Пожалуйста, помогите, это действительно важно и сдерживает меня в течение нескольких дней. Все, что я хочу сделать, это иметь возможность получать стихи из любого набора глав, который я выберу в книге.
Комментарии:
1. Почему я не могу сказать
where chapter.Index().Value == state.getChapterNumber()
Ответ №1:
Ну, для начала, я не думаю, что вы хотели второго потомка в целом — вы хотели вторую главу, что не обязательно одно и то же. К счастью, это легко сделать:
// Use 1 for the second chapter, 2 for "element 2" (i.e. the third element) etc
var chapter = book.Descendants("chapter").ElementAt(1);
var verses = from verse in chapter...
РЕДАКТИРОВАТЬ: Для номера стиха используйте перегрузку Select
, которая предоставляет индекс элемента:
var verses = chapter.Element("verse")
.Select((element, index) => new {
VerseNumber = index 1,
Text = element.Value
});
Лично я не думаю, что для каждого стиха имеет смысл иметь первый и последний стих в абзаце. На самом деле это не особенность этого стиха, не так ли?
Комментарии:
1. Ваша простая техника программирования тоже помогла. Может быть, вы сможете помочь выяснить, как я могу заставить linq возвращать количество итераций для каждого,
select new
чтобы у меня былоVerseNumber = THE ITERATION,
вместо строки выше. Мог бы я написать что-то вродеVerseNumber = verse.Index().Value,
2. Мой друг, ты спас мне жизнь! Я готовлю праздничный напиток прямо сейчас! Вот что я сделал (все благодаря вам). Я создал класс с именем
Verse
, который содержал все мои переменные. И затем я использовал вашу технику следующим образом.var verses = book.Descendants("c").ElementAt(state.GetChapter() - 1).Descendants("p").Elements() .Select((element, index) => new Verse { VerseNumber = (index 1).ToString(), ScriptureText = element.Value });
Это сработало отлично! Большое вам спасибо!3. Если я тоже могу спросить вас, есть ли способ преобразовать это в linq sql? Как бы вы написали перегрузку select? Другими словами, как бы вы написали это
Select((element, index) => new Verse { element, index });
в формате linq sql?4. @GuyMicciche: Под «форматом LINQ SQL», я полагаю, вы подразумеваете выражение запроса? (
from x in y where x.foo select x.bar
?) В синтаксисе выражения запроса нет поддержки для этой перегрузки.5. @JonSkeet У меня похожий случай, но для меня стихи уникальны, как я могу получить индекс главы?
Ответ №2:
Еще один правильный ответ, хотя ответ Джона Скита намного эффективнее, заключается в следующем коде:
chapter.ElementsBeforeSelf().Count()
Ответ №3:
Используя обозначение метода расширения, вы можете использовать Select()
вызов, который предоставит вам индекс текущего элемента следующим образом:
var indexedChapters = book.Decendants().Select((Chapter, Index) => new { Chapter, Index });
После этого вы можете получить доступ к индексу анонимного типа в любом следующем операторе linq.
Комментарии:
1. В моем операторе linq после оператора ‘from’ мой оператор where выглядит следующим образом:
where book.Decendants("c").Index == state.GetChapterNumber()
По сути, я извлекаю значение из функции, чтобы получить соответствующую позицию xml-элемента на основе этого значения. Не могли бы вы помочь, кажется, вы направили меня в правильном направлении.2. У меня проблема посерьезнее. Где у меня есть
VerseNumber = verse.Attribute("n").Value,
Мне нужно значение VerseNumber каждый раз, чтобы перебирать количество стихов в XML-файле для каждой главы. О боже.