How to sort XML files using node attribute in C #

Don't ask someone to code this solution for me - just look for recommendations on the best approach. I am working on a .aspx file in VS2015 using C # code.

I have found countless threads explaining how to sort nodes in an XML file. But I did not find a single topic on how to sort multiple XML files with the same structure according to the common child attribute of node.

My situation: I have a directory of hundreds of XML files with the name, simply, 0001.xml through 6400.xml. Each XML file has the same structure. I want to sort the files (not the nodes) according to the attribute of the node child.

Each XML file has a parent element "item" node and has child nodes "year", "language" and "author", among others. For example:

<item id="0001">
   <year>2011</year>
   <language id="English" />
   <author sortby="Smith">John F. Smith</author>
   <content></content>
</item>

If instead of listing the files in order from 0001 to 6400, I instead want to list them alphabetically according to the item / author node @sortby attribute, how would I do this?

One of my ideas was to create a temporary XML file that collects the information needed for each XML file. Then I can sort the temporary XML file and then scroll through the nodes to display the files in the correct order. Something like that...

XDocument tempXML = new XDocument();
// add parent node of <items>

string[] items = Directory.GetFiles(directory)
foreach (string item in items)
{
   // add child node of <item> with attributes "filename", "year", "language", and "author"
}

// then sort the XML nodes according to attributes
It makes sense? Is there a smarter way to do this?
+4
source share
5 answers

xml , LINQ to Xml, :

var xmlsWithFileName = Directory.GetFiles(directory)
                                .Select(fileName => new { fileName, xml = XDocument.Parse(File.ReadAllText(fileName)) })
                                .OrderBy(tuple => tuple.xml.Element("item").Element("author").Attribute("sortby").Value);

xmlsWithFileName

  • xml , XML XDocument
  • fileName, XML

, xml:

0001.xml

<item id="0001">
   <year>2011</year>
   <language id="English" />
   <author sortby="Smith">John F.Smith</author>
   <content></content>
</item>

0002.xml

<item id="0002">
   <year>2012</year>
   <language id="Portuguese" />
   <author sortby="Monteiro">Alberto Monteiro</author>
   <content></content>
</item>

public static void ShowXmlOrderedBySortByAttribute(string directory)
{
    var xmlsWithFileName = Directory.GetFiles(directory)
                                    .Select(fileName => new { fileName, xml = XDocument.Parse(File.ReadAllText(fileName)) })
                                    .OrderBy(tuple => tuple.xml.Element("item").Element("author").Attribute("sortby").Value);

    foreach (var xml in xmlsWithFileName)
    {
        Console.WriteLine($"Filename: {xml.fileName}{Environment.NewLine}Xml content:{Environment.NewLine}");
        Console.WriteLine(xml.xml.ToString());
        Console.WriteLine("================");
    }
}

:

Filename: c:\temp\teste\0002.xml
Xml content:

<item id="0002">
  <year>2012</year>
  <language id="Portuguese" />
  <author sortby="Monteiro">Alberto Monteiro</author>
  <content></content>
</item>
================
Filename: c:\temp\teste\0001.xml
Xml content:

<item id="0001">
  <year>2011</year>
  <language id="English" />
  <author sortby="Smith">John F.Smith</author>
  <content></content>
</item>
================

, XML 0002.xml , 0001.xml

+4

Edit: , , , , , , , "items" , GetAuthor .

, - , . Lookup:

var lookup = items.ToLookup(a => GetAuthor(a)).OrderBy(a => a.Key);

, :

private string GetAuthor(string filename)
{
    string author = String.Empty;

    // get author name logic

    return author;
}

, , :

foreach (IGrouping<string, string> author in lookup)
{
    foreach (string file in author)
    {
        Console.WriteLine(String.Format("{0}: {1}", author.Key, file ));
    }
}

, , , IComparer, , .

+2

, , :

SortedDictionary<string, string> dict = new SortedDictionary<string, string>();
var files = Directory.GetFiles(@"[path to files]", "*.xml");

foreach (var item in files)
{
    XDocument doc = XDocument.Load(item);
    var sortvalue = (from lv1 in doc.Descendants("somesortvalue")
                     select lv1.Value).First();

    dict.Add(sortvalue, item);
}

foreach dict.keys, .

+1

XML InnerText

  • Linq . - childnode, .
  • XSLT

. XML InnerText XMLElement

Hope this helps!

+1
source

You can load items with XElementand sort them as follows:

var items = System.IO.Directory.GetFiles(@"path", "*.xml")
                     .Select(file => System.Xml.Linq.XElement.Load(file));
                     .OrderBy(x => x.Element("author").Attribute("sortby").Value)
                     .ToList();

Also, if you need file names, you can select an object containing FileNameandItem:

var items = System.IO.Directory.GetFiles(@"path", "*.xml")
                     .Select(file => new
                     {
                         FileName = file, 
                         Item = System.Xml.Linq.XElement.Load(file)
                     })
                     .OrderBy(x => x.Item.Element("author").Attribute("sortby").Value)
                     .Select(x=>x.FileName) /*or .Select(x=>x.Item)*/
                     .ToList();
+1
source

Source: https://habr.com/ru/post/1622297/


All Articles