2015-07-10 3 views
0

У меня есть xml-файл со следующей структурой;Печать вложенных анонимных типов

<Product ID="Sample A" UserTypeID="TYPE_PRD_RANGE"> 
     <MultiValues> 
     <Value> 
     <Value AttributeId = "Att_1">Value1</Value> 
     </MultiValues> 
     <Values AttributeId = "Att_2"> 
     <Value AttributeId = "Att_3">Value1</Value> 
     <Value AttributeId = "Att_4">Value2</Value> 
     <Value AttributeId = "Att_5">Value3</Value> 
     <Value AttributeId = "Att_6">Value4</Value> 
     </Values> 
     <Product ID="Sample A_1" UserTypeID="SUB_RANGE"> 
     <Values AttributeId = "Att_2_5"> 
      <Value AttributeId = "Att_2_4">Value1</Value> 
      <Value AttributeId = "Att_2_3">Value2</Value> 
      <Value AttributeId = "Att_2_1">Value3</Value> 
      <Value AttributeId = "Att_2_2">Value4</Value> 
     </Values> 
     </Product> 
     <Product ID="Sample A_1_1" UserTypeID="ITEM"> 
     <Values AttributeId = "12345"> 
      <Value AttributeId = "Att_2_1_1">Value1</Value> 
      <Value AttributeId = "Att_2_2_1">Value2</Value> 
      <Value AttributeId = "Att_2_3_1">Value3</Value> 
      <Value AttributeId = "Att_2_4_1">Value4</Value> 
     </Values> 
     </Product>  
    </Product> 

У меня есть запрос LINQ, подобный приведенному ниже с двумя вложенными анонимных типов

var rangeProducts = xml.Descendants("Product") 
        .Where(x => (string)x.Attribute("UserTypeID") == TYPE_PRD_RANGE); 

var rangeproductDetails = rangeProducts.Select(x => new 
     { 

      ID = (String)x.Attribute("ID"), 
      UserTypeID = (String)x.Attribute("UserTypeID"), 
           Values = x.Descendants("Value") 
           .Where(y => (string)y.Attribute("AttributeID") == "Att_1"), 

      //sub group for PRD_SUB_RANGE 
      descendants = x.Descendants("Product") 
         .Where(y => (string)y.Attribute("UserTypeID")=="TYPE_PRD_SUBRANGE") 
         .Select(n => new 
     { 
      //group for items. 
      children = n.Descendants("Product") 
          .Where(y => (string)y.Attribute("UserTypeID") == "ITEM") 
          .Select(m => new 
      { 

       ID = (String)m.Attribute("ID"), 
       UserTypeID = (String)m.Attribute("UserTypeID"), 
       Values = m.Descendants("Value") 
        .Where(y =>(string)y.Attribute("AttributeID")) == "Att_2_1_1"), 
      }, 

      //for PRD_SUB_RANGE 
      ID = (String)n.Attribute("ID"), 
      UserTypeID = (String)n.Attribute("UserTypeID"), 
      Values = n.Descendants("Value") 
       .Where(y => ((string)y.Attribute("AttributeID")) == "Att_2_4"), 

     }) 

Я пытаюсь выписать результаты запроса на консоль или в текстовый файл, находящийся в следующий формат

"range_Product ID" ,"range_Attribute 1.Value", 
    "subrange Product_ID", "subrange_Attribute2.Value" 
     Item Product_ID, "item_Attribute_1.Value" ,"item_Attribute_2.Value" 
     Item Product_ID, "item_Attribute_1.Value" ,"item_Attribute_2.Value" 

в настоящее время я могу сделать что-то похожее на это:

"range_Product ID" ,"range_Attribute 1.Value", 
    "subrange Product_ID", "subrange_Attribute2.Value" 
    "subrange Product_ID", "subrange_Attribute2.Value" 
     Item Product_ID, "item_Attribute_1.Value" ,"item_Attribute_2.Value" 
     Item Product_ID, "item_Attribute_1.Value" ,"item_Attribute_2.Value" 

Но я хотел бы, чтобы каждый элемент под каждым поддиапазон был распечатан первым. Я лаяю здесь неправильное дерево или это возможно даже отдаленно? У меня были предложения просто десериализовать XML в POCOs, но никто не смог сказать, возможно ли то, что я ищу.

EDIT: Образец Требуемый выход.

"Sample A" "Value1" 
    "Sample A_1" "Value3" 
    Sample A_1_1 "Value 1" "Value 2" 
    Sample A_1_2 "Value1" "Value2" 
+0

1) Ваш XML не анализирует: ' Значения>' должно быть '', а второе' 'должно быть, вероятно,' '. Можете ли вы подтвердить и обновить свой вопрос> 2) Я немного смущен относительно того, что вы хотите, можете ли вы дать свой желаемый результат для конкретного образца XML в своем вопросе? – dbc

+0

@ dbc. Ой, ты прав. Я отредактировал с образцом вывода. –

ответ

0

Преобразование XML вывод текста, как таковой, безусловно, выполним. Несколько предложений

Во-первых, я не вижу преимущества использования анонимного типа здесь. имея определенный класс высшего уровня, чтобы сосать всю необходимую информацию в ИМО, значительно облегчило бы рассуждать о форме данных, с которыми вы работаете. Это не значит, что вам нужно сериализовать; вы все же можете вручную заполнить объект из XML, что, вероятно, меньше работает, и позволяет лучше определить форму конца.

Затем можно связать метод с классом, который выводит свои данные на консоль так, как вы посчитаете нужным (даже просто переопределить ToString())

Также проверьте метод расширения XPathEvaluate. Это сделает ваш XML-запрос более понятным и сжатым.

EDIT: Поскольку вы предоставили образец того, что вы хотите, вот решение

public void OutputProductElement(XElement inElem, int inIndentLevel) 
{ 
    string theIndentation = new string(Enumerable.Repeat('\t', inIndentLevel).ToArray()); 

    var theValueElements = inElem.XPathSelectElements("MultiValues/Value").Concat(
     inElem.XPathSelectElements("Values/Value") 
     ); 

    string theValueList = string.Join(" ", theValueElements.Select(elem => @"""" + elem.Value + @"""")); 

    Console.Out.WriteLine(theIndentation + @"""" + (string)inElem.Attribute("ID") + @""" " + theValueList ); 

    //no print all children elemnts 
    inElem.Elements("Product").ToList().ForEach(elem => OutputProductElement(elem, inIndentLevel + 1)); 
} 

А вот выход:

"Sample A" "Value1" "Value1" "Value2" "Value3" "Value4" 
    "Sample A_1" "Value1" "Value2" "Value3" "Value4" 
    "Sample A_1_1" "Value1" "Value2" "Value3" "Value4" 

Надеется, что я не просто делать свою домашнюю работу для вы :)

+0

Ха-ха, просто увидел ваше редактирование. Это не домашнее задание. Я пытаюсь создать некоторые файлы конфигурации для Tekla Warehouse, и на данный момент это медленно. Не могли бы вы рассказать о «ручном заполнении объекта из XML». –

+0

. Я имел в виду, что заполнение класса данными XML вручную (с использованием кода C# и linq) было бы примерно так же просто, как десериализация в моем сознании.Но на самом деле, если вы просто выводите его как строку куда-то, набирая все данные в класс ma, переполняйте, вместо этого просто напишите рекурсивную функцию, подобную приведенной выше (если я поймаю ваш дрейф до тех пор, пока желаемый выход). Просто перейдите в «Корень» вашего XDocument и 0 для уровня отступа. Надеюсь, это поможет. – slimbofat

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