2016-09-06 2 views
0

У меня есть список XML-элементов, хранящихся в классе:Получение конкретных элементов из XDocument на основе списка

public class clsField 
{ 
    public string fieldName { get; set; } 
} 

Тогда я загрузке файла XML:

XDocument doc = XDocument.Load(fileName); 

Наконец, я хочу для получения только полей, определенных в указанном выше классе, в объект IEnumerable. Это то, что у меня есть до сих пор:

List<clsField> lstFieldsToProcess;   
IEnumerable<XElement> allthedocs = from thedoc 
       in doc.Descendants("thedocs") 
       select 
       (
        from fields 
        in lstFieldsToProcess 
        select XElement.Parse(fields.fieldName) 
       ); 

Но я получаю сообщение об ошибке по вышеуказанному коду. Любая помощь будет оценена по достоинству. Спасибо за руку.

Update # 1

Псевдо код:

var fieldNames = new HashSet<string>(lstFieldsToProcess.Select(c => c.fieldName)); 
IEnumerable<XElement> elems = from level1 in doc.Elements("thedocs") 
           let level2 = level1.Descendants() 
           where fieldNames.Contains(level2.Name.LocalName) 
           select level1; 
+3

'получение ошибки на вышеуказанный код' как насчет обмена с нами? –

+0

Является ли 'clsField' объектом, который сериализуется в документе' fileName'? Или у вас есть произвольный объект, сериализованный, и вы хотите получить имена свойств * другого * класса (в этом случае class 'clsField') и получать только поля из XML-документа, которые соответствуют именам свойств, найденным в' clsField '? – Quantic

+0

Последнее верно. clsField - это отдельный класс, который содержит имя свойства полей, которые я хотел бы получить из «Документа XDocument». Благодарю. –

ответ

1

Я не совсем уверен, что вы пытаетесь сделать. Вы хотите отфильтровать все элементы с определенным именем и быть потомком элемента (ов) с именем «thedocs»?

Если предположить, что это то, что вы хотите сделать, то вы можете сделать следующее:

IEnumerable<XElement> elems = from field in lstFieldsToProcess 
           from de in doc.Elements("thedocs").Descendants(field.fieldName) 
           select de; 

// Of course this is the same: 
IEnumerable<XElement> elems = lstFieldsToProcess 
    .SelectMany(f => doc.Elements("thedocs").Descendants(f.fieldName)); 

Я не уверен, насколько эффективно XDocument это, хотя, так что, возможно, лучше вынуть имена полей, которые требуется матч первого (пожалуйста, тест, который является лучшим из двух, если производительность важна для вас):

var fieldNames = new HashSet<string>(lstFieldsToProcess.Select(c => c.fieldName)); 
IEnumerable<XElement> elems = from d in doc.Elements("thedocs").Descendants() 
           where fieldNames.Contains(d.Name.LocalName) 
           select d; 

Update # 1 Я думаю, почти у его самостоятельно в вашем псевдокод.

var fieldNames = new HashSet<string>(lstFieldsToProcess.Select(c => c.fieldName)); 
IEnumerable<XElement> elems = from level1 in doc.Elements("thedocs") 
           from level2 in level1.Descendants() 
           where fieldNames.Contains(level2.Name.LocalName) 
           select level1; 

Хотя, это может содержать то же «thedocs» элемент много раз (если он имеет несколько потомков с действительным имя_полем). Чтобы этого избежать, просто вызовите Distint() в результате.

+0

Kennet спасибо! Почти готово. Он правильно выбирает поля из потомков. Теперь как мне вернуться: «doc.Elements (« thedocs »)» вместо «doc.Elements (« thedocs »). Потомки»? Поля выбраны, но окончательный формат, который мне нужен, это просто «doc.Elements (« thedocs »)». Благодарю. –

+0

@RobertSmith: Что значит «вернуться»? Если вы измените эти элементы (например, значение) каким-либо образом, они также будут изменены в вашей переменной doc в памяти. Итак, чтобы получить новый xml (с измененными значениями) в виде строк (по одному на элемент «Документы»), вы можете просто сделать: 'doc.Elements (« theDocs »). Выберите (e => e.ToString())' Конечно, если у вас есть только один элемент «theDocs», вы можете: doc.Element («theDocs»). ToString() ' – Kennet

+0

Kennet, это трудно объяснить. См. «Обновление № 1» выше. Поля, которые необходимо выбрать, на один уровень глубже («level2» выше). Но оператор select должен выбрать «level1». –

Смежные вопросы