2012-02-02 3 views
1

У меня есть XML, который выкладывается для переформатирования в вложенные заголовки HTML-таблицы. Я работаю над тем, чтобы каждый уровень XML-документа был включен в собственный список. Например:Build List <Список <XElement>> from XML

<column name="Total" size="0"> 
    <column name="Users" size="0" /> 
</column> 
<column name="Date" size="0" /> 
<column name="Unique" size="0"> 
    <column name="Clicks" size="0"> 
    <column name="RC" size="0" /> 
    <column name="CB" size="0" /> 
    </column> 
</column> 

Из этого примера, столбцы «Total», «Дата» и «Unique» должно быть в первом списке. Столбцы «Пользователи» и «Клики» должны быть во втором списке. И столбцы «RC» и «CB» должны быть в третьем списке. Это должно быть выполнено с помощью рекурсии, чтобы сделать метод полностью динамичным. Любая помощь приветствуется.

+0

'' недопустимый XML. Сначала проясните это. –

+0

@HenkHolterman - Разве они не все * недопустимые XML? –

+0

Да. Они есть. Это всего лишь пример данных. Я уточню что-то ближе к тому, с чем я работаю. – Joe

ответ

1

Здесь вы идете:

XElement root = XElement.Parse(@" 
    <doc> 
     <column1> 
     <column2 /> 
     </column1> 
     <column3 /> 
     <column4> 
     <column5> 
      <column6 /> 
      <column7 /> 
     </column5> 
     </column4> 
    </doc>"); 

List<List<XElement>> outerList = new List<List<XElement>>(); 
List<XElement> innerList = root.Elements().ToList(); 
while (innerList.Any()) 
{ 
    outerList.Add(innerList); 
    innerList = innerList.SelectMany(element => element.Elements()).ToList(); 
} 

Редактировать: Если вы хотите, чтобы лишить предков XElement экземпляров их потомков в списке, то вы можете использовать следующие:

XElement root = XElement.Parse(@" 
    <table> 
     <column name=""Total"" size=""0""> 
     <column name=""Users"" size=""0"" /> 
     </column> 
     <column name=""Date"" size=""0"" /> 
     <column name=""Unique"" size=""0""> 
     <column name=""Clicks"" size=""0""> 
      <column name=""RC"" size=""0"" /> 
      <column name=""CB"" size=""0"" /> 
     </column> 
     </column> 
    </table>"); 

List<List<XElement>> outerList = new List<List<XElement>>(); 
IEnumerable<XElement> innerList = root.Elements(); 
while (innerList.Any()) 
{ 
    outerList.Add(innerList.Select(e => new XElement(e.Name, e.Attributes())).ToList()); 
    innerList = innerList.SelectMany(element => element.Elements()); 
} 

Примечание: Для записи ваша интуиция, что вы должны использовать рекурсию, была правильной. Однако также хорошо известно, что любая рекурсивная функция может быть преобразована в итерацию, как правило, путем моделирования стека. Иногда это приводит к раздутому коду; однако в других случаях преобразование само собой разумеется. В вашем случае, если вы должны были рекурсивно, вашим рекурсивным параметром были бы непосредственные дети из набора элементов, которые в настоящее время рассматриваются, которые уже доступны в innerList, что позволяет нам использовать трюк innerList = innerList.<SequenceOperation> для замены рекурсии.

+0

Это прекрасно. Спасибо. – Joe

+0

Это имеет смысл. Опять же, я очень ценю вашу помощь в этом. – Joe

+0

Добро пожаловать :-) – Douglas

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