Синтаксис метода Linq для выравнивания узлов xml - PullRequest
0 голосов
/ 30 мая 2019

Ниже приведен рабочий код для выравнивания узлов xml:

var xml = XDocument.Parse(input);

var headerSection = xml.Descendants("Header");
var subHeaderSection = xml.Descendants("SubHeader");

var body = xml.Descendants("Body");
var activity = body.Descendants("Activity");
var position = body.Descendants("Position");
var positionAmouts = position.Descendants("PositionAmounts").Elements("PositionAmount");

var results = from h in headerSection
              from sh in subHeaderSection
              from a in activity              
              from po in position
              from pa in positionAmouts
              select new List<string>
              {
                  h.Element("Id").Value,
                  h.Element("OtherId").Value,
                  h.Element("SomeValue").Value,
                  sh.Element("SomeValue2").Value,
                  sh.Element("SomeValue3").Value,
                  a.Element("ActivityId").Value,
                  a.Element("ActivityValue").Value,
                  po.Element("PositionId").Value,
                  pa.Element("Amount1").Value,
                  pa.Element("Amount2").Value,
              }

Этот код работает нормально.Но фактический список предложений длиннее, чем показано.И инициатор списка становится большим длинным списком значений.

Я полагаю, что если я смогу преобразовать многие froms в синтаксис метода linq, я смогу получить те же самые результаты List в методе, где я могу сделать что-то лучше, чем перечислить все нужные значения?(как цикл по некоторым предварительно определенным именам элементов)

Редактировать: образец xml по запросу:

<Root>
  <Header>
    <Id>123</Id>
    <OtherId>456</OtherId>
    <SomeValue>abc</SomeValue>    
  </Header>
  <SubHeader>
    <SomeValue2>dfg</SomeValue2>
    <SomeValue3>fghj</SomeValue3>    
  </SubHeader>
  <Body>
    <Activity>
      <ActivityId>321</ActivityId>
      <ActivityValue>hjk</ActivityValue>      
    </Activity>    
    <Position>
      <PositionId>654</PositionId>      
      <PositionAmounts>
        <PositionAmount>
          <Amount1>10.01</Amount1>
          <Amount2>12.63</Amount2>          
        </PositionAmount>
        <PositionAmount>
          <Amount1>15.11</Amount1>
        </PositionAmount>        
      </PositionAmounts>
    </Position>
  </Body>
</Root>

1 Ответ

0 голосов
/ 31 мая 2019

Попробуйте так:

const string splitterElementName = "PositionAmount";

var doc = XDocument.Parse(input);

var result = doc.Descendants()
    // Take just the deepest descendants.
    .Where(v => !v.HasElements)
    .Select(v => v.AncestorsAndSelf())
    // Group by key, where key contains names of all ancestors exclude the deepest element.
    .GroupBy(k =>
        {
            var isSplitter = false;

            var key = string.Join("-", k
                .Skip(1)
                .Select(v =>
                {
                    if (v.Name.LocalName != splitterElementName)
                    {
                        return v.Name.LocalName;
                    }

                    isSplitter = true;

                    // Define the unique id for each splitting element.
                    return $"{v.Name.LocalName}:{string.Join(":", v.AncestorsAndSelf().Select(a => a.ElementsBeforeSelf().Count()))}";
                }));

            return (key, isSplitter);
        },
        e => e.First().Value)
    // Merge all groups to one list.
    .GroupBy(k => 0, e => e, (key, element) => element.ToArray())
    // Extract all splitters.
    .SelectMany(groups => groups
        .Where(group => group.Key.isSplitter)
        .Select(splittingGroup => (splittingKey: splittingGroup.Key, groups)))
    // Prepare result.
    .Select(v => v.groups
        .Where(group => !group.Key.isSplitter || group.Key == v.splittingKey)
        .SelectMany(a => a)
        .ToArray())
    .ToList();

    /* result:
    [0]: {string[10]}
    [1]: {string[9]}
result[0]
{string[10]}
    [0]: "123"
    [1]: "456"
    [2]: "abc"
    [3]: "dfg"
    [4]: "fghj"
    [5]: "321"
    [6]: "hjk"
    [7]: "654"
    [8]: "10.01"
    [9]: "12.63"
result[1]
{string[9]}
    [0]: "123"
    [1]: "456"
    [2]: "abc"
    [3]: "dfg"
    [4]: "fghj"
    [5]: "321"
    [6]: "hjk"
    [7]: "654"
    [8]: "15.11"
     */

Тест xml:

var input = @"<Root>
  <Header>
    <Id>123</Id>
    <OtherId>456</OtherId>
    <SomeValue>abc</SomeValue>    
  </Header>
  <SubHeader>
    <SomeValue2>dfg</SomeValue2>
    <SomeValue3>fghj</SomeValue3>    
  </SubHeader>
  <Body>
    <Activity>
      <ActivityId>321</ActivityId>
      <ActivityValue>hjk</ActivityValue>      
    </Activity>    
    <Position>
      <PositionId>654</PositionId>      
      <PositionAmounts>
        <PositionAmount>
          <Amount1>10.01</Amount1>
          <Amount2>12.63</Amount2>          
        </PositionAmount>
        <PositionAmount>
          <Amount1>15.11</Amount1>
        </PositionAmount>        
      </PositionAmounts>
    </Position>
  </Body>
</Root>";
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...