如何为xml元素之间的数据编写linq到xml
本文关键字:xml linq 数据 之间 元素 | 更新日期: 2023-09-27 18:25:08
我正在尝试解析一些类似于以下内容的XML:
<document>
<headings>
Important heading stuff.
</headings>
<startGroup group="1" />
<startItem value="1" />Item one stuff<endItem />
<blockofdata>
<startItem value="2" />Item two stuff<endItem />
<startItem value="3" />Item three stuff<endItem />
</blockofdata>
<startItem value="4" />Item four stuff<endItem />
<endGroup />
<startGroup group="2" />
<startItem value="1" />Item one stuff<endItem />
<startItem value="2" />Item two stuff<endItem />
<startItem value="3" />Item three stuff<endItem />
<endGroup />
</document>
我无法找到一个linq-to-xml语句来获得我想要的内容。我需要把结构弄平。因此,假设上面的XML,我想得到这个POCO:的列表
class Items
{
public int GroupNumber {get;set;} // group property of startGroup
public int ItemNumber {get;set;} // value property of startItem
public string ItemText {get;set;} // data between i
}
如何编写linq-to-xml语句,将属性之间的数据拉入上述项,同时从startGroup/endGroup之间获取数据,并从startItem/endItem之间获取数据?我在这方面已经花了几个小时,即将改用XML流读取器并以老式的方式对其进行解析。
这里的关键是使用ElementsAfterSelf()
和NodesAfterSelf()
方法来获取同级节点以及TakeWhile()
谓词,以便在适当的时候停止枚举。
首先是助手方法:
public static Items ItemsFromStartItem(XElement start, XElement group)
{
return new Items
{
GroupNumber = (int)group.Attribute("group"),
ItemNumber = (int)start.Attribute("value"),
ItemText = start.NodesAfterSelf()
.TakeWhile(n => n.NodeType != XmlNodeType.Element
|| ((XElement)n).Name != "endItem")
.OfType<XText>()
.Select(t => t.Value)
.Single()
};
}
public static IEnumerable<Items> ItemsFromBlockOfData(
XElement block, XElement group)
{
return block.Elements("startItem")
.Select(start => ItemsFromStartItem(start, group));
}
还有神奇的查询。
var query = doc.Descendants("startGroup")
.SelectMany(group => group.ElementsAfterSelf()
.TakeWhile(e => e.Name != "endGroup")
.SelectMany(e => e.Name == "startItem"
? new[] { ItemsFromStartItem(e, group) }
: ItemsFromBlockOfData(e, group))
);
现在我希望您没有自己设计这个XML。。。这种东西真的会把人推向边缘。)