我收到如下的xml消息(相信我这不是我想要的):
<items>
<item item="A" position="0">
<itemvalue>10</itemvalue>
</item>
<item item="A" position="1">
<itemvalue>20</itemvalue>
</item>
<item item="A" position="2">
<itemvalue>30</itemvalue>
</item>
<item item="B" position="0">
<itemvalue>10</itemvalue>
</item>
<item item="B" position="1">
<itemvalue>20</itemvalue>
</item>
<item item="B" position="2">
<itemvalue>30</itemvalue>
</item>
</items>
我正在使用LINQ粉碎XML。所以我得到的是项目清单职位|值。我真的希望数据与我的表结构相匹配。
Item | Column1 | Column2 | Column3
A 10 20 30
对于我来说,获取该List以及构建可以传递给DB的单独对象的最佳方法是什么。现在我得到明确的项目列表(这里是A&amp; B),然后将其传递给Lambda表达式,这样我就可以说给出Item = A和Position = X(0,1,2)的值。
只是想知道什么是最好的方法来“压扁”这个结构不良的XML。
答案 0 :(得分:2)
<强>代码:强>
static void Main(string[] args)
{
var xml = XDocument.Parse("<items><item item=\"A\" position=\"0\"><itemvalue>10</itemvalue></item><item item=\"A\" position=\"1\"><itemvalue>20</itemvalue>"
+ "</item><item item=\"A\" position=\"2\"><itemvalue>30</itemvalue></item><item item=\"B\" position=\"0\"><itemvalue>10</itemvalue>"
+ "</item><item item=\"B\" position=\"1\"><itemvalue>20</itemvalue></item><item item=\"B\" position=\"2\"><itemvalue>30</itemvalue>"
+ "</item></items>").Root;
var keys = xml.Elements()
.GroupBy(x => x.Attribute("item").Value)
.Select(x => x.Key);
var flattened = new XDocument();
flattened.Add(new XElement("flattened"));
foreach (var item in keys)
{
var elements = xml.Elements().Where(x => x.Attribute("item").Value == item);
flattened.Root.Add(new XElement("Item", new XAttribute("Item", elements.First().Attribute("item").Value)
, new XAttribute("Column1", elements.First().Element("itemvalue").Value)
, new XAttribute("Column2", elements.ElementAt(1).Element("itemvalue").Value)
, new XAttribute("Column3", elements.Last().Element("itemvalue").Value)));
}
Console.WriteLine(flattened.ToString());
Console.ReadLine();
}
<强>结果:强>
答案 1 :(得分:1)
在item
属性上阅读xml和分组。
var result = from ele in doc.Descendants("item")
group ele by ele.Attribute("item").Value into grp
select grp;
foreach (var t in result)
{
XElement[] ar = t.ToArray();
Console.WriteLine(t.Key + " "+ ar[0].Value + " " + ar[1].Value + " " + ar[2].Value );
}
答案 2 :(得分:1)
您可以编写XSLT来重新排列内容,我对使用XML作为编程语言深感厌恶。缂!
不过,这样的事情应该是这样的。一个小的XML序列化和一个非常简单的转换:using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication22
{
[XmlRoot( "items" )]
public class ItemList
{
public static ItemList CreateInstance( string xml )
{
ItemList instance = null ;
using ( TextReader tr = new StringReader( xml ) )
{
XmlSerializer serializer = new XmlSerializer(typeof(ItemList)) ;
instance = (ItemList) serializer.Deserialize( tr ) ;
}
return instance ;
}
public SimpleItem[] Simplify()
{
return Items.OrderBy( x => x.Name )
.ThenBy( x => x.Position )
.GroupBy( x => x.Name , x => x , (name,group) => SimpleItem.CreateInstance(name,group) )
.ToArray()
;
}
[XmlElement("item")]
public Item[] Items { get ; set ; }
}
public class Item
{
[XmlAttribute("item")]
public string Name { get ; set ; }
[XmlAttribute("position")]
public int Position { get ; set ; }
[XmlElement("itemvalue")]
public int Value { get ; set ; }
}
public class SimpleItem
{
public static SimpleItem CreateInstance( string name , IEnumerable<Item> items )
{
List<int> values = new List<int>() ;
int i = 0 ;
foreach( Item item in items.OrderBy( x => x.Position ) )
{
if ( item.Position != i++ ) throw new InvalidOperationException("bad data") ;
values.Add(item.Value) ;
}
SimpleItem instance = new SimpleItem(name , values.ToArray() ) ;
return instance ;
}
private SimpleItem( string name , int[] values )
{
this.Name = name ;
this.Columns = values ;
return ;
}
public string Name { get ; private set ; }
public int[] Columns { get ; private set ; }
}
class Program
{
static void Main( string[] args )
{
string xml = @"
<items>
<item item=""A"" position=""0"">
<itemvalue>10</itemvalue>
</item>
<item item=""A"" position=""1"">
<itemvalue>20</itemvalue>
</item>
<item item=""A"" position=""2"">
<itemvalue>30</itemvalue>
</item>
<item item=""B"" position=""0"">
<itemvalue>10</itemvalue>
</item>
<item item=""B"" position=""1"">
<itemvalue>20</itemvalue>
</item>
<item item=""B"" position=""2"">
<itemvalue>30</itemvalue>
</item>
</items>
" ;
ItemList instance = ItemList.CreateInstance(xml) ;
SimpleItem[] items = instance.Simplify() ;
return ;
}
}
}
答案 3 :(得分:0)
你在做什么可能是最好的方法。使用XSLT转换可以尝试一些魔法,但是当面对像你一直困扰的病态格式时,它们往往会变得脆弱。
答案 4 :(得分:0)
如果你无法控制xml的格式,我能想到的最好的事情就是使用结构并在lambda中实例化/填充一个实例,将对象输出到列表中。你走在正确的轨道上。