Linq方法语法以扁平化xml节点

时间:2019-05-30 01:23:26

标签: c# linq linq-to-xml

我有下面的工作代码可以展平xml节点:

value_counts

此代码可以正常工作。但是发件人的实际列表比显示的要长。并且列表启动器成为一长串的值列表。

我相信,如果我可以将许多froms转换为linq方法语法,那么我应该能够在一种方法中产生比列出所有所需值更好的方法的相同List结果吗? (例如循环遍历一些预定义的元素名称)

编辑:根据要求提供示例xml:

med562['IND']=med562['IND'].replace({'':'I'})

Catcounts=med562.IND.value_counts(dropna=False)

1 个答案:

答案 0 :(得分:0)

尝试这种方式:

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>";