2016-06-07 62 views
0

我正在开发一个应用程序C#并试图完成XML我从JSON得到。并且对于XML对我的应用程序有效,我需要在父元素下将具有相同名称的元素分组。 例如,我得到这个XML比较每个级别的XML中的节点名称

<root> 
<row> 
    <id>0001</id> 
    <type>credit</type> 
    <investment>1000</investment> 
    <ppr>0.83</ppr> 
    <candidate> 
     <id>5001</id> 
     <name>Hugo</name> 
    </candidate> 
    <candidate> 
     <id>5002</id> 
     <name>Jack</name> 
    </candidate> 
    <candidate> 
     <id>5005</id> 
     <name>Kate</name> 
    </candidate> 
</row> 

我需要将所有与该名候选人的元素,下一个父节点的候选人,这样

<root> 
<row> 
    <id>0001</id> 
    <type>credit</type> 
    <investment>1000</investment> 
    <ppr>0.83</ppr> 
<candidates> 
     <candidate> 
       <id>5001</id> 
       <name>Hugo</name> 
     </candidate> 
     <candidate> 
       <id>5002</id> 
       <name>Jack</name> 
     </candidate> 
     <candidate> 
       <id>5005</id> 
       <name>Kate</name> 
     </candidate> 
</candidates> 
</row> 

但这是我的问题:我不知道我可以从JSON收到的名称。所以我需要做这个比较,并在不知道“候选”节点名称的情况下完成XML。我需要这个名字,我可以接受。

也在这个例子中,XML只有2个级别,但它可以有任意数量的级别。我可以遍历XML没有问题,此功能:

public void findAllNodes(XmlNode node) 
{ 
    Console.WriteLine(node.Name); 
    foreach (XmlNode n in node.ChildNodes) 
    findAllNodes(n); 
} 

我怎样才能作出比较和组中的节点?

回答

2

一个相当天真的实现可以使用LINQ按名称对元素进行分组,并为那些在组中有多个项目的元素添加父元素。这将是递归的,因此元素的子元素被分组,直到树枯竭。

天真性是,如果存在混合的内容元素,这样的解决方案会中断,并且将不是兄弟姐妹的元素分组(基本上,这两个问题都会导致事情以错误的顺序结束)。它应该给你一个好的开始,并可能足以满足你的目的。

private static IEnumerable<XElement> GroupElements(IEnumerable<XElement> elements) 
{ 
    var elementsByName = elements.GroupBy(x => x.Name); 

    foreach (var grouping in elementsByName) 
    { 
     var transformed = grouping.Select(e => 
      new XElement(e.Name, 
       GroupElements(e.Elements()), 
       e.Attributes(), 
       e.Nodes().OfType<XText>())); 

     if (grouping.Count() == 1) 
     { 
      yield return transformed.Single(); 
     } 
     else 
     { 
      var groupName = grouping.Key + "s"; 
      yield return new XElement(groupName, transformed); 
     } 
    } 
} 

您可以通过解析/加载现有的XML,然后转化根元素,并从这些创建新文档时使用此:

var original = XDocument.Parse(xml); 
var grouped = new XDocument(GroupElements(original.Elements())); 

了工作演示见this fiddle

+0

非常感谢您!这正是我正在寻找的 – FRassetto

+0

它也适用于我!谢谢 –

0

下面是一个XSLT 2.0解决方案:

​​

输出:

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <row> 
     <id>0001</id> 
     <type>credit</type> 
     <investment>1000</investment> 
     <ppr>0.83</ppr> 
     <candidates> 
     <candidate> 
      <id>5001</id> 
      <name>Hugo</name> 
     </candidate> 
     <candidate> 
      <id>5002</id> 
      <name>Jack</name> 
     </candidate> 
     <candidate> 
      <id>5005</id> 
      <name>Kate</name> 
     </candidate> 
     </candidates> 
    </row> 
</root> 

限制

  • 它不处理混合内容(有孩子的元素加文本内容)

  • 它丢弃属性(容易固定)