Gå til innhold

C#: Sortering av XML (Inkl. forsøk på kode)


Anbefalte innlegg

Hei!

 

Prøver å lage en high-score "tabell" ved bruk av en richTextBox, men sliter litt.

Har sittet med dette i 8 timer så begynner å rotne litt i huet. Tenkte derfor å høre om noen her hadde noen innspill å komme med ang. hvorfor dette ikke fungerer.

 


private void button2_Click(object sender, EventArgs e)
       //XXXXXXXXXXXXXXXXXXX HER SKRIVES SCORE TABELLEN XXXXXXXXXXXXXXXXXXXXXXX
       {
           if (!File.Exists("highscore.xml"))
           {

               XmlTextWriter textWritter = new XmlTextWriter("highscore.xml", null);
               textWritter.WriteStartDocument();
               textWritter.WriteStartElement("Brukere");
               textWritter.WriteEndElement();

               textWritter.Close();
           }

           XmlDocument xmlDoc = new XmlDocument();
           //laster filen hvis den finnes fra før
           xmlDoc.Load("highscore.xml");

           XmlElement subRoot = xmlDoc.CreateElement("bruker");
           //bruker
           XmlElement appendedElementBrukernavn = xmlDoc.CreateElement("brukernavn");
           XmlText xmlTextBrukernavn = xmlDoc.CreateTextNode("Brukernavn: " + textBox1.Text.Trim());
           appendedElementBrukernavn.AppendChild(xmlTextBrukernavn);
           subRoot.AppendChild(appendedElementBrukernavn);
           xmlDoc.DocumentElement.AppendChild(subRoot);
           //brukernavn

           XmlElement appendedElementScore = xmlDoc.CreateElement("score");
           XmlText xmlTextScore = xmlDoc.CreateTextNode(label3.Text.Trim());
           appendedElementScore.AppendChild(xmlTextScore);
           subRoot.AppendChild(appendedElementScore);
           xmlDoc.DocumentElement.AppendChild(subRoot);
           //score

           XmlElement appendedElementLevel = xmlDoc.CreateElement("level");
           XmlText xmlTextLevel = xmlDoc.CreateTextNode(richTextBox1.Text.Trim());
           appendedElementLevel.AppendChild(xmlTextLevel);
           subRoot.AppendChild(appendedElementLevel);
           xmlDoc.DocumentElement.AppendChild(subRoot);
           //level
           xmlDoc.Save("highscore.xml");

           // XXXXXXXXXXXXXXXXX HER LESES SCORETABELLEN XXXXXXXXXXXXXXXXXXXX

           richTextBox2.Visible = true;

           String s = "";
           richTextBox2.Text = "";
           try
           {

               XmlTextReader reader = new XmlTextReader("highscore.xml");
               while (reader.Read())
               {
                   switch (reader.NodeType)
                   {
                       case (XmlNodeType.Element):
                           {
                               if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "Brukere"))
                               {
                                   if (reader.HasAttributes)
                                   {
                                       richTextBox2.Text = ((reader.GetAttribute("score") + "\n" + reader.GetAttribute("brukernavn") + "\n" + reader.GetAttribute("level")));
                                   }

                               }
                               break;
                           }

                       case (XmlNodeType.Text):
                           {
                               s = s + reader.Value + "\n";

                               break;
                           }

                   }
               }
               XmlDocument doc = new XmlDocument();

               doc.Load("highscore.xml");
               XPathNavigator navigator = doc.CreateNavigator();
               XPathExpression expression = navigator.Compile("Brukere/bruker");
               expression.AddSort("brukernavn", XmlSortOrder.Descending, XmlCaseOrder.UpperFirst,
                   string.Empty, XmlDataType.Text);
               XPathNodeIterator iterator = navigator.Select(expression);

               richTextBox2.Text = s;

               reader.Close();
           }
           catch (Exception f)
           {
               Console.WriteLine(f.Message);
               MessageBox.Show("Kunne ikke aksessere filen");
           }
       }

 

Driver å lærer C# på skolen nå så vær snille :)

 

Takker så mye for all hjelp.

Endret av Niggorex
Lenke til kommentar
Videoannonse
Annonse

Hvis vi velger å se helt bort fra koden du har skrevet så vil jeg heller fokusere på konseptet.

 

Hvis du kun har par med navn og poengsum så kan du bruke en dictionary<string, int> for å representere disse. Du kan da sortere på verdien med LINQ. Når du har den sorterte listen så er det bare å skrive verdiene til hvor det måtte være.

 

Håper det setter deg på rett spor.

Lenke til kommentar

Jeg hadde tenkt til å si "ARGH! BRUK LINQ! ØYNENE MINE EKSPLODERER!" men hvis det er en skoleoppgave kan jeg forstå. Men jeg mener fortsatt at du burde bruke LINQ. Det er helt håpløst å rote med det utrolig dårlige manuelle XML API-et.

 

legg til #using System.Xml.Linq så vil du få XElement, XNode etc.

 

Du kan kanskje start med å kikke på dokumentasjonen til XDocument. Er et eksempel helt nederst på siden (som ikke tar i bruk select dog)

 

For å lese tilbake er det mye simplere å få til dette med Linq

 

Edit: Det er forøvrig kanskje enklere å benytte XmlSerializer til dette fremfor å lese manuelt.

 

Edit2:

Fungerende eksempel ved å benytte XmlSerializer

 

 

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Serialization;

namespace HighscoreExample
{
   public class Program
   {
       static readonly XmlSerializer Serializer = new XmlSerializer(typeof(Highscore));

       static void Main()
       {
           Highscore score = null;

           // Dersom datasettet eksisterer
           if(File.Exists("highscore.xml"))
               // Vi åpner en fil, og passer på å lukke den etter bruk ved å benytte oss av using mønsteret
               using (var fs = File.Open("highscore.xml", FileMode.Open))
                   // Les innholdet fra filen og bruk XmlSerializer til å oversette XML innholdet
                   score = Serializer.Deserialize(fs) as Highscore;

           if (score == null)
           {
               // Dersom filen ikke eksisterer, eller ikke var gyldig så fyller vi inn eksempeldata
               score = PopulateGarbage();
               // Skriv eksempeldata til fil
               using (var fs = System.IO.File.Open("highscore.xml", FileMode.Create))
                   // La XmlSerializeren gjøre om objektdata til en XML fil, og skriv innholdet til filen vi har åpnet
                   Serializer.Serialize(fs, score);
           }

           int index = 0;
           // Gå igjennom alle elementer sortert i synkende rekkefølge etter poeng, og ta maksimum ti elementer
           foreach (var item in score.GetItemsOrderedByScore().Take(10))
               // Skriv ut poenglisten
               Console.WriteLine(string.Format("{0}.{1}", ++index, item));
       }

       // denne funksjonen lager noe eksempeldata
       static Highscore PopulateGarbage()
       {
           Highscore result = new Highscore();
           result.Items.Add(new HighscoreEntry() { Level = 1, Score = 100, UserName = "ASS"});
           result.Items.Add(new HighscoreEntry() { Level = 1, Score = 50, UserName = "ABC" });
           result.Items.Add(new HighscoreEntry() { Level = 1, Score = 256, UserName = "QQQ" });
           result.Items.Add(new HighscoreEntry() { Level = 1, Score = 95, UserName = "123" });
           result.Items.Add(new HighscoreEntry() { Level = 1, Score = 80, UserName = "LOL" });
           return result;
       }
   }
   [XmlInclude(typeof(HighscoreEntry))]
   public class Highscore
   {
       public Highscore()
       {
           // Pass på at Items alltid har en liste i seg
           Items = new List<HighscoreEntry>();
       }

       public IEnumerable<HighscoreEntry> GetItemsOrderedByScore()
       {
           // Ta alle elementer i Items og sorter dem i synkende rekkefølge etter score
           return Items.OrderByDescending(item => item.Score);
       }

       public List<HighscoreEntry> Items { get; set; }
   }
   public class HighscoreEntry
   {
       public int Level { get; set; }
       public long Score { get; set; }
       public string UserName { get; set; }

       public override string ToString()
       {
           // Lag en representativ string av dataene
           return string.Format("{0}\t{1} ({2})", UserName, Score, Level);
       }
   }
}

 

Endret av GeirGrusom
Lenke til kommentar

Tusen takk for hjelp begge to. Kjempeflott! :)

 

Vi hadde faktisk om LINQ dagen etter jeg spurte om dette, men må innrømme at jeg skjønte fint lite av det. Skal sette meg ned med koden du kom med Geir, og prøve å forstå litt mer.

 

Takk igjen :)

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...