我有以下XML文档(必要时可以重新设计),用于存储记录和错误。
<MYROOT>
<RECORDS>
<RECORD>
<DATETIME>11/03/2010 14:12:41</DATETIME>
<DOCUMENTID>1</DOCUMENTID>
</RECORD>
<RECORD>
<DATETIME>11/03/2010 14:12:44</DATETIME>
<DOCUMENTID>2</DOCUMENTID>
</RECORD>
<RECORD>
<DATETIME>11/03/2010 14:12:45</DATETIME>
<DOCUMENTID>3</DOCUMENTID>
</RECORD>
</RECORDS>
<ERRORS>
<ERROR TYPE="ERR">
<DATETIME>11/03/2010 14:12:41</DATETIME>
<DETAIL>There has been a error on page 1</DETAIL>
</ERROR>
<ERROR TYPE="ERR">
<DATETIME>11/03/2010 14:13:03</DATETIME>
<DETAIL>There has been a error on page 101</DETAIL>
</ERROR>
<ERROR TYPE="SEQ">
<DATETIME>11/03/2010 14:13:03</DATETIME>
<DETAIL>Sequence Error, expected Sequence No. 101 Read 1</DETAIL>
</ERROR>
</ERRORS>
</MYROOT>
我想输出记录和错误,但显然必须按日期对它们进行排序,以便按顺序显示。
如何按日期对它们进行排序,获取XElements的集合,然后只对它们进行foreach循环?
答案 0 :(得分:3)
XDocument xml = System.Xml.Linq.XDocument.Parse(YOUR_XML);
IEnumerable<XElement> records = xml.Root.Element("RECORDS").Elements();
IEnumerable<XElement> errors = xml.Root.Element("ERRORS").Elements();
IEnumerable<XElement> elements = from el in records.Concat(errors)
orderby DateTime.Parse(el.Element("DATETIME").Value)
select el;
foreach (XElement el in elements)
{
// do something.
}
答案 1 :(得分:1)
var elements = doc.Descendants("RECORD").Concat(doc.Descendants("ERROR")).
OrderBy(x => DateTime.Parse(x.Element("DATETIME").Value));
foreach (XElement element in elements)
{
// do something interesting with element
}
答案 2 :(得分:0)
IEnumerable不是很灵活,最好的选择可能是从枚举中删除元素,对它们进行排序并重新插入它们,保持正确的顺序(相对于以前的邻居)。如果子元素是排序键
,则会更复杂一些这将从IEnumerable中删除指定的元素,按子元素对它们进行排序(可能是您需要的也可能不是),然后将它们重新插入到正确的位置。
private void SortIdNodes(XElement parent, String elementName, String sortElementname)
{
XNode prevElem = null;
XNode nextElem = null;
// Initial node count, to verify sets are equal
int initialElementsCount = parent.Descendants().Count();
List<XElement> unOrdered = parent.Descendants(elementName).ToList<XElement>();
if (unOrdered.Count() < 2){
return; // No sorting needed
}
// Make note of the neighbors
prevElem = unOrdered[0].PreviousNode;
nextElem = unOrdered.Last().NextNode;
// Remove set from parent
unOrdered.ForEach(el =>
{
el.Remove();
});
// Order the set, language (IEnumerable) semantics prevents us from changing order in place
List <XElement> ordered = unOrdered.OrderBy(x => x.Descendants(sortElementname).FirstOrDefault().Value).ToList<XElement>();
// Add to parent in correct order
if (prevElem != null) // If there's a first neighbor
{
ordered.ForEach(el =>
{
prevElem.AddAfterSelf(el);
prevElem = el;
});
}
else if (nextElem != null) // If there's only an end neighbor
{
ordered.Reverse();
ordered.ForEach(el =>
{
nextElem.AddBeforeSelf(el);
nextElem = el;
});
}
else // we're the only children of the parent, just add
{
ordered.ForEach(el =>
{
parent.Add(el); // add in order
});
}
int finalElementCount = parent.Descendants().Count();
if (initialElementsCount != finalElementCount)
{
throw new Exception("Error with element sorting, output collection not the same size as the input set.");
}
}