Gwendalin Posted April 12, 2017 Share Posted April 12, 2017 Does anyone know how to read an xml file in C#? Specifically a certain tag? Â I have an xml document that has the following information <game name="Arctic Zone (Europe)" index="true" image="a"> Â Â Â Â Â Â <description>Arctic Zone (Europe)</description> Â Â Â Â Â Â <cloneof></cloneof> Â Â Â Â Â Â <crc>f88f2d25</crc> Â Â Â Â Â Â <manufacturer>Commin</manufacturer> Â Â Â Â Â Â <year>1993</year> Â Â Â Â Â Â <genre>Action</genre> Â Â Â Â Â Â <rating>HSRS - GA (General Audience)</rating> Â Â Â Â Â Â <enabled>Yes</enabled> Â Â Â </game> Â I am able to read the inner nodes like the <crc> but I cant figure out how to get the information in the start element. I need to get the <game name="name"> part at the top. Link to comment Share on other sites More sharing options...
panda Posted April 12, 2017 Share Posted April 12, 2017 I don't actually know the API myself, but those should be called something akin to "attribute". Edit: Use the Attributes property. Link to comment Share on other sites More sharing options...
Kevin Posted April 12, 2017 Share Posted April 12, 2017 XmlDocument doc = new XmlDocument(); doc.Load("yourxml.xml"); XmlNodeList elemList = doc.GetElementsByTagName("game"); for (int i=0; i < elemList.Count; i++) { Console.WriteLine(elemList.InnerXml); }  or  XmlTextReader reader = null; try { eader = new XmlTextReader("yourxml.xml"); reader.MoveToContent(); string name = reader.GetAttribute("Name"); Console.WriteLine("Your game name :" + name); Link to comment Share on other sites More sharing options...
Gwendalin Posted April 12, 2017 Author Share Posted April 12, 2017 I thought edited my post to add my code, but it didnt save. Â This is the code I have. i have the reader.GetAttribute("Name") in the messagebox but it doesn't do anything; My messagebox for the CRC does work so i know it's reading the xml correctly. Â using (XmlReader reader = XmlReader.Create(database)) { while (reader.Read()) { if (reader.IsStartElement()) { switch (reader.Name.ToString()) { case "game": MessageBox.Show("name " + reader.GetAttribute("game name")); //MessageBox.Show("Game Name: " + reader.ReadString()); break; case "crc": //MessageBox.Show("CRC" + reader.ReadString()); break; } } } } Â Â EDIT: Â Ok i tried getting the attribute "index" and that works.... but i can't get the index "game name" Â Â EDIT 2: Â OK i'm ditzy... figured it out. I was thinking the index was "game name"... but the node is game.. the index is "name". I had it right the entire time... i was just dancing around the answer. Thanks everyone. jcsnider 1 Link to comment Share on other sites More sharing options...
panda Posted April 12, 2017 Share Posted April 12, 2017 2 minutes ago, Gwen said: I thought edited my post to add my code, but it didnt save. Â This is the code I have. i have the reader.GetAttribute("Name") in the messagebox but it doesn't do anything; My messagebox for the CRC does work so i know it's reading the xml correctly. Â using (XmlReader reader = XmlReader.Create(database)) { while (reader.Read()) { if (reader.IsStartElement()) { switch (reader.Name.ToString()) { case "game": MessageBox.Show("name " + reader.GetAttribute("game name")); //MessageBox.Show("Game Name: " + reader.ReadString()); break; case "crc": //MessageBox.Show("CRC" + reader.ReadString()); break; } } } } Â You should be using reader.GetAttribute("name") or reader["name"] not reader.GetAttribute("game name"). Link to comment Share on other sites More sharing options...
Gwendalin Posted April 12, 2017 Author Share Posted April 12, 2017 Thanks Panda, i realized that right after I posted my code. panda 1 Link to comment Share on other sites More sharing options...
Gwendalin Posted April 12, 2017 Author Share Posted April 12, 2017 Yay! This is the first thing I've programed in like 4 years. I did steal some code... all of the CRC code, but I'm excited with what I have done considering I haven't looked at code in forever. Â It is to help me organize my rom collection. Over the years i have downloaded multiple copies of different systems and I know that a lot of them are the same file just named differently. I was going through my directories manually to clean them out but some systems have thousands of games, and that would take me forever. I know there are utilities to clean a single folder, but i have not come across anything that will compare to directories together. Â This program will read two folders, and give me the crc of each file in the folder. It also reads the XML database of the frontend I'm using. This way i can see if i have duplicate files in the two drives, and see if my roms are named correctly with my frontend and have the same crc. Â Next i have to sort the table so the files will match up with the database name and crc, and have the files in the directories match up if they have the same crc so i can tell if i have a duplicate. After that I'm going to try to add in auto deleting of duplicates. Â Unfortunately it is an ugly program, and i dont have any error checking so it is easily breakable, but maybe i'll fix that later. Â i did break something recently when i was messing with adding the xml code, so my data is not correct in this screen shot, but it was working earlier. Â Giligis, panda and jcsnider 3 Link to comment Share on other sites More sharing options...
Gwendalin Posted April 14, 2017 Author Share Posted April 14, 2017 Can someone help me with this. I'm trying to create a list of data that contains a name+crc entry each time it comes up in the xml. I've been having trouble getting the name and crc to match up as the xml is being read, but i finally have them matching.  The messagebox before i add the object to the list displays the correct data. So I would assume that the object i'm adding to the list is correct. Before i return the list i am checking my list and stepping through each entry. The problem is it seems like only the last entry in my xml is in my list.  I have 9 xml entries, and the foreach shows the last xml entry 9 times.  So the xml is reading correctly. I am able to display each name+crc property correctly in the first messagebox... it displays 9 different entries. When i add it to the list, it does add 9 items, but when i display them, they are all the last name+crc entry recorded.  here are two of 9 entries... the second messagbox in my code only shows the commin 5 in 1 entry 9 times.  I hope i explained that ok.  class XMLData { private string name; private string crc; private string database; private List<XMLData> dEntries; public string Name { get { return name; } } public string CRC { get { return crc; } } public XMLData(string directory) { database = directory; dEntries = new List<XMLData>(); ReadXML(); } private XMLData() { } private List<XMLData> ReadXML() { using (XmlReader reader = XmlReader.Create(database)) { while (reader.Read()) { if (reader.IsStartElement()) { switch (reader.Name.ToString()) { case "game": this.name = reader.GetAttribute("name"); break; case "crc": this.crc = reader.ReadString(); MessageBox.Show("Name: " + this.Name + " Crc: " + this.CRC); dEntries.Add(this); break; } } } } foreach (XMLData x in dEntries) { MessageBox.Show("for Name: " + x.Name + " Crc: " + x.CRC); } return dEntries; } }  Link to comment Share on other sites More sharing options...
panda Posted April 14, 2017 Share Posted April 14, 2017 35 minutes ago, Gwen said: Can someone help me with this. I'm trying to create a list of data that contains a name+crc entry each time it comes up in the xml. I've been having trouble getting the name and crc to match up as the xml is being read, but i finally have them matching.  The messagebox before i add the object to the list displays the correct data. So I would assume that the object i'm adding to the list is correct. Before i return the list i am checking my list and stepping through each entry. The problem is it seems like only the last entry in my xml is in my list.  I have 9 xml entries, and the foreach shows the last xml entry 9 times.  So the xml is reading correctly. I am able to display each name+crc property correctly in the first messagebox... it displays 9 different entries. When i add it to the list, it does add 9 items, but when i display them, they are all the last name+crc entry recorded.  here are two of 9 entries... the second messagbox in my code only shows the commin 5 in 1 entry 9 times.  I hope i explained that ok.  class XMLData { private string name; private string crc; private string database; private List<XMLData> dEntries; public string Name { get { return name; } } public string CRC { get { return crc; } } public XMLData(string directory) { database = directory; dEntries = new List<XMLData>(); ReadXML(); } private XMLData() { } private List<XMLData> ReadXML() { using (XmlReader reader = XmlReader.Create(database)) { while (reader.Read()) { if (reader.IsStartElement()) { switch (reader.Name.ToString()) { case "game": this.name = reader.GetAttribute("name"); break; case "crc": this.crc = reader.ReadString(); MessageBox.Show("Name: " + this.Name + " Crc: " + this.CRC); dEntries.Add(this); break; } } } } foreach (XMLData x in dEntries) { MessageBox.Show("for Name: " + x.Name + " Crc: " + x.CRC); } return dEntries; } }  Source XML? Link to comment Share on other sites More sharing options...
Gwendalin Posted April 14, 2017 Author Share Posted April 14, 2017 here is what the xml doc looks like. Â <?xml version="1.0"?> <menu> <header> <listname>Creatronic Mega Duck</listname> <lastlistupdate>03/06/2016</lastlistupdate> <listversion>1.0</listversion> <exporterversion>HyperList XML Exporter Version 1.3 Copywrite (c) 2009-2011 William Strong</exporterversion> </header> <game name="Arctic Zone (Europe)" index="true" image="a"> <description>Arctic Zone (Europe)</description> <cloneof></cloneof> <crc>f88f2d25</crc> <manufacturer>Commin</manufacturer> <year>1993</year> <genre>Action</genre> <rating>HSRS - GA (General Audience)</rating> <enabled>Yes</enabled> </game> <game name="Commin 5 in 1 (Europe)" index="true" image="c"> <description>Commin 5 in 1 (Europe)</description> <cloneof></cloneof> <crc>ff0da355</crc> <manufacturer>Commin</manufacturer> <year>1993</year> <genre>Miscellaneous</genre> <rating>HSRS - GA (General Audience)</rating> <enabled>Yes</enabled> </game> <game name="Magical Tower (Europe)" index="true" image="m"> <description>Magical Tower (Europe)</description> <cloneof></cloneof> <crc>98694021</crc> <manufacturer>Sachen</manufacturer> <year>1993</year> <genre>Action</genre> <rating>HSRS - GA (General Audience)</rating> <enabled>Yes</enabled> </game> <game name="Mega Duck 4 in 1 Game (Europe)" index="" image=""> <description>Mega Duck 4 in 1 Game (Europe)</description> <cloneof></cloneof> <crc>8046ea70</crc> <manufacturer>Sachen</manufacturer> <year>1993</year> <genre>Miscellaneous</genre> <rating>HSRS - GA (General Audience)</rating> <enabled>Yes</enabled> </game> <game name="Pile Wonder (Europe)" index="true" image="p"> <description>Pile Wonder (Europe)</description> <cloneof></cloneof> <crc>61c81e06</crc> <manufacturer>Commin</manufacturer> <year>1993</year> <genre>Action</genre> <rating>HSRS - GA (General Audience)</rating> <enabled>Yes</enabled> </game> <game name="Railway (Europe)" index="true" image="r"> <description>Railway (Europe)</description> <cloneof></cloneof> <crc>2bb6aeb9</crc> <manufacturer>Sachen</manufacturer> <year>1993</year> <genre>Action</genre> <rating>HSRS - GA (General Audience)</rating> <enabled>Yes</enabled> </game> <game name="Street Rider (Europe)" index="true" image="s"> <description>Street Rider (Europe)</description> <cloneof></cloneof> <crc>74c3377f</crc> <manufacturer>Commin</manufacturer> <year>1993</year> <genre>Driving</genre> <rating>HSRS - GA (General Audience)</rating> <enabled>Yes</enabled> </game> <game name="Suleimans Treasure (Europe)" index="" image=""> <description>Suleimans Treasure (Europe)</description> <cloneof></cloneof> <crc>cd2730ac</crc> <manufacturer>Commin</manufacturer> <year>1993</year> <genre>Action</genre> <rating>HSRS - GA (General Audience)</rating> <enabled>Yes</enabled> </game> <game name="The Brick Wall (Europe)" index="true" image="t"> <description>The Brick Wall (Europe)</description> <cloneof></cloneof> <crc>58efe338</crc> <manufacturer>Timlex International</manufacturer> <year>1993</year> <genre>Action</genre> <rating>HSRS - GA (General Audience)</rating> <enabled>Yes</enabled> </game> </menu> Â Link to comment Share on other sites More sharing options...
Gwendalin Posted April 14, 2017 Author Share Posted April 14, 2017 each entry shows correctly with the first messagebox. the second messagebox shows the brick wall 9 times. Link to comment Share on other sites More sharing options...
panda Posted April 14, 2017 Share Posted April 14, 2017 Oh, because you're overwriting the name and CRC and then the second message box is just looping through a list of this. Basically, your code is logically broken and doesn't achieve what you want it to. Not sure what it's supposed to do though. tl;dr: What is your code supposed to be doing? Link to comment Share on other sites More sharing options...
Gwendalin Posted April 14, 2017 Author Share Posted April 14, 2017 I thought that since I store the values into the list before changing the value a second time, it would just add a new entry with the new value. Since im overwriting the data, shouldint i only have one entry in my list. Why does it create the correct amount of entries, but overwrites the value in the list, when i'm not accessing the list data?  i want it to read through the xml file, and grab the <game Name> attribute, and the <crc> attribute. I need to store that data as a pair in an array or list that i can iterate through later and put into my grid, that i have in my previous post.  I want to store that data that is shown in the two messagebox images above into a list.  read xml.. create object with .name, and .crc property store object in a list  object 1 = obj1.name = "game1" | obj1.crc = "crc value" object 2 = obj2.name = "game2" | obj2.crc = "crc value" etc....   Link to comment Share on other sites More sharing options...
panda Posted April 14, 2017 Share Posted April 14, 2017 You aren't adding the value to the list, you're adding a reference to the value to the list. I imagine the list allows duplicates. Â I'd suggest making ReadXML a static method, with either internal or public ass the access modifier, and you should move the directory parameter to the ReadXML method. Above reader.Read() I would declare a data variable (XMLData data = null;), and when it reads the game element I would check if it's set, if so, add it to the list, and regardless of whether data was null or not, assign it a new instance of XMLData. After the while loop is complete, check if data is null, and if it isn't, add it to the list. Don't bother adding it to the list in the CRC case, I imagine you will be adding other elements to your object and then there isn't a guarantee of ordering. Link to comment Share on other sites More sharing options...
Gwendalin Posted April 15, 2017 Author Share Posted April 15, 2017 Can you give me an example... Im not following. Â This always happens... i start off good, then try to add or change something to try to make it easier, then get stuck on something that should be pretty simple and get discouraged. Link to comment Share on other sites More sharing options...
panda Posted April 15, 2017 Share Posted April 15, 2017 class XMLData { private static List<XMLData> dEntries; private string name; private string crc; public string Name { get { return name; } } public string CRC { get { return crc; } } public XMLData() { } public static List<XMLData> ReadXML(string database) { using (XmlReader reader = XmlReader.Create(database)) { XMLData data = null; while (reader.Read()) { if (reader.IsStartElement()) { switch (reader.Name.ToString()) { case "game": if (data != null) { MessageBox.Show("Name: " + data.Name + " Crc: " + data.CRC); dEntries.Add(data); } data = new XMLData(); data.name = reader.GetAttribute("name"); break; case "crc": data.crc = reader.ReadString(); break; } } } if (data != null) { MessageBox.Show("Name: " + data.Name + " Crc: " + data.CRC); dEntries.Add(data); } } foreach (XMLData x in dEntries) { MessageBox.Show("for Name: " + x.Name + " Crc: " + x.CRC); } return dEntries; } } IPB is dicking with the tab/space formatting but this should still be legible. Edit: If not, https://pastebin.com/XRmuEnE4 Link to comment Share on other sites More sharing options...
Gwendalin Posted April 17, 2017 Author Share Posted April 17, 2017 Thanks Panda, Â I'll give this a try! I appreciate your help!!! Link to comment Share on other sites More sharing options...
Gwendalin Posted April 17, 2017 Author Share Posted April 17, 2017 not working...  i get this error "Additional information: Object reference not set to an instance of an object."  It displays the correct information for the first entry in the xml file, and then breaks. in this section. The dEntries.add(data); is highlighted. if (data != null) { MessageBox.Show("Switch Name: " + data.Name + " Crc: " + data.CRC); dEntries.Add(data); } if i comment that out it will display all the entries in the xml correctly, but it then breaks in the second if (data != null) part when adding the data. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now