【问题标题】:Ordering XElements订购 XElement
【发布时间】:2011-01-26 10:37:12
【问题描述】:

我有以下存储记录和错误的 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>

我想输出记录和错误,但显然必须按日期对它们进行排序,以便它们按顺序显示。

如何按日期对它们进行排序,获取 XElement 集合,然后对它们执行 foreach 循环?

【问题讨论】:

    标签: c# linq .net-3.5 c#-3.0 linq-to-xml


    【解决方案1】:
    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.
    }
    

    【讨论】:

      【解决方案2】:
      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
      }
      

      【讨论】:

        【解决方案3】:

        IEnumerable 不是很灵活,最好的选择可能是从 enumerable 中删除元素,对它们进行排序并重新插入它们,保持正确的顺序(相对于以前的邻居)。如果子元素是排序键

        ,会稍微复杂一些

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

        【讨论】:

          猜你喜欢
          • 2011-08-03
          • 1970-01-01
          • 1970-01-01
          • 2020-09-08
          • 2017-09-14
          • 2013-04-10
          • 2012-10-04
          • 2012-09-21
          • 2011-07-18
          相关资源
          最近更新 更多