订购XElements

3

我有一个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循环遍历它们?
3个回答

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
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
}

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.");
         }
     }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接