Can't seem to read XML attributes

Hey guys,

Before I write this question, I feel like I should mention that I have spent a good deal of time searching the internet, and trying solutions, but I can’t seem to get this right.

I am trying to read XML into a custom class to fill it with information, which I will use to sort a these classes. My XML document consists of both elements and attributes, and they will all be read in order, from top to bottom.

The problem I’m currently facing is that I can’t read attributes, because it seems to stop reading if I try to access them. I think that reader.IsStartElement may exclude attributes, but I tried other methods, and not only did they have the same problem, but they also gave me a lot of empty debug messages.

My code is bellow- I tried to trim it a bit to conserve space, but if I haven’t posted enough, please let me know. Also, if you need to see my XML document, I’d be happy to post that, but I don’t think there is a problem with it. Uncommenting either of the two lines near the bottom causes my XML reader to stop reading (or, that’s what it appears to do).

using System;
using System.IO;
using System.Xml;
using System.Net;
using UnityEngine;
using System.Linq;
using System.Threading;
using System.Diagnostics;
using System.Collections;
using System.ComponentModel;
using System.Xml.Serialization;
using System.Collections.Generic;
//Written by GibsonBethke
//Thanks to Mike Talbot
[XmlRoot("Songs")]
public class SongCollection
{
	
	[XmlElement("Song")]
	public Song[] Songs;
}


public class Song
{
	
	public String name;

	public Album album;
	public Artist artist;
	public Genre genre;

	public String format;
	public String downloadLink;
	[XmlElement("Link")]
         public Link[] Links;
	
	public String releaseDate;
}


public class Link
{
	
	[XmlAttribute]
	public string name;
	[XmlText]
	public string link;
}


public class Album : IEquatable<Album>
{
	
	public String name;
	public List<Song> songs;
	
	public Album (String Name, List<Song> Songs)
	{
		
		this.name = Name;
		this.songs = Songs;
	}
	
	public bool Equals(Album other)
	{
		if (other == null) return false;
		return (this.name.Equals(other.name));
	}
}

public class Artist : IEquatable<Artist>
{
	
	public String name;
	public List<Song> songs;

	public Artist (String Name, List<Song> Songs)
	{

		this.name = Name;
		this.songs = Songs;
	}

	public bool Equals(Artist other)
	{
		if (other == null) return false;
		return (this.name.Equals(other.name));
	}
}

public class Genre : IEquatable<Genre>
{

	public String name;
	public List<Song> songs;

	public Genre (String Name, List<Song> Songs)
	{
		
		this.name = Name;
		this.songs = Songs;
	}
	
	public bool Equals(Genre other)
	{
		if (other == null) return false;
		return (this.name.Equals(other.name));
	}	
}

public class OnlineMusicBrowser : MonoBehaviour
{
	
	StartupManager startupManager;
	MusicViewer musicViewer;
	PaneManager paneManager;

	#region OMBVariables

	public GUISkin guiSkin;
	GUIStyle labelStyle;
	GUIStyle infoLabelStyle;
	GUIStyle buttonStyle;
	GUIStyle boxStyle;
	
	public Texture2D guiHover;
	public Texture2D guiActiveHover;
	
	internal bool showOnlineMusicBrowser = false;

	Vector2 scrollPosition;
	internal Rect onlineMusicBrowserPosition = new Rect(0, 0, 800, 600);
	internal string onlineMusicBrowserTitle;
	
	internal bool showDownloadList = false;

	#region Lists
	
	string[] allSongs;
	List<Song> allRecentList;
	List<Song> allSongsList;
	List<Album> allAlbumsList;
	List<Artist> allArtistsList;
	List<Genre> allGenresList;
	List<Song> specificSort;
	
	#endregion
	
	int sortBy = 5;
	string currentPlace = "Recent";

	#endregion
	
	#region DownloadInformation
	
	Song songInfoOwner;
	
	public WebClient client;
	
	Uri url;
//	Song song;
	string downloadButtonText;
	
	string currentDownloadSize;
	string currentDownloadPercentage;
	
	bool showSongInformation = false;
	bool downloading = false;
	
	Song downloadingSong;
	
	#endregion
	

	void Start ()
	{

		startupManager = GameObject.FindGameObjectWithTag ( "Manager" ).GetComponent<StartupManager>();
		musicViewer = GameObject.FindGameObjectWithTag ( "MusicViewer" ).GetComponent<MusicViewer>();
		paneManager = GameObject.FindGameObjectWithTag ("Manager").GetComponent<PaneManager>();

		onlineMusicBrowserPosition.width = Screen.width;
		onlineMusicBrowserPosition.height = Screen.height;
		onlineMusicBrowserPosition.x = onlineMusicBrowserPosition.width + onlineMusicBrowserPosition.width / 4;
		
		labelStyle = new GUIStyle ();
		labelStyle.alignment = TextAnchor.MiddleCenter;
		labelStyle.wordWrap = true;
		
		infoLabelStyle = new GUIStyle ();
		infoLabelStyle.alignment = TextAnchor.MiddleLeft;
		infoLabelStyle.fontSize = 16;
		
		buttonStyle = new GUIStyle ();
		buttonStyle.fontSize = 16;
		buttonStyle.alignment = TextAnchor.MiddleCenter;
		buttonStyle.border = new RectOffset ( 6, 6, 4, 4 );
		buttonStyle.hover.background = guiHover;
	}
	

	void StartOMB ()
	{
		
		allSongs = null;
		allRecentList = new List<Song> ();
		allSongsList = new List<Song> ();
		allAlbumsList = new List<Album> ();
		allArtistsList = new List<Artist> ();
		allGenresList = new List<Genre> ();
		specificSort = new List<Song> ();
		
		Thread refreshThread = new Thread ( SortAvailableDownloads );
		refreshThread.Start();
	}
	
	
	void SortAvailableDownloads()
	{
		
//		allSongs = startupManager.allSongs;

/*		int i = 0;

		while (i < allSongs.Length)
		{
			
			i += 9;
			Song song = new Song();
			song.name = allSongs [i - 8];
			
			Album tempAlbum = new Album(allSongs [i - 7], new List<Song>());
			if(allAlbumsList.Contains (tempAlbum))
			{
				
				Album addToAlbum = allAlbumsList.Find(Album => Album.name == tempAlbum.name);
				addToAlbum.songs.Add (song);
				song.album = tempAlbum;
			} else {
				
				tempAlbum.songs.Add (song);
				allAlbumsList.Add (tempAlbum);
				song.album = tempAlbum;
			}
			
			Artist tempArtist = new Artist(allSongs [i - 6], new List<Song>());
			if(allArtistsList.Contains (tempArtist))
			{
				
				Artist addToArtist = allArtistsList.Find(Artist => Artist.name == tempArtist.name);
				addToArtist.songs.Add (song);
				song.artist = tempArtist;
			} else {
				
				tempArtist.songs.Add (song);
				allArtistsList.Add (tempArtist);
				song.artist = tempArtist;
			}
			
			Genre tempGenre = new Genre(allSongs [i - 5], new List<Song>());
			if(allGenresList.Contains (tempGenre))
			{
				
				Genre addToGenre = allGenresList.Find(Genre => Genre.name == tempGenre.name);
				addToGenre.songs.Add (song);
				song.genre = tempGenre;
			} else {
				
				tempGenre.songs.Add (song);
				allGenresList.Add (tempGenre);
				song.genre = tempGenre;
			}
			
			
			song.format = allSongs [i - 4];
			song.downloadLink = allSongs [i - 3];
			song.supportLink = allSongs [i - 2];
			song.releaseDate = allSongs [i - 1];
			
			allSongsList.Add ( song );
			allRecentList.Add ( song );
		}
*/
		Song tempSong = new Song ();
		Album tempAlbum;
		Artist tempArtist;
		Genre tempGenre;
		using (XmlReader reader = XmlReader.Create ( startupManager.supportPath + Path.DirectorySeparatorChar + "Downloads.xml" ))
		{
			
		    while (reader.Read ())
		    {
				
				if ( reader.IsStartElement ())
				{
					
					switch (reader.Name)
					{

						case "Name":
							if (reader.Read ())
							{
						
								tempSong = new Song ();
								
								tempSong.name = reader.Value.Trim ();
								UnityEngine.Debug.Log ( tempSong.name );
							}
					    break;
						case "Album":
							if (reader.Read ())
							{
						
								tempAlbum = new Album ( reader.Value.Trim (), new List<Song> ());
								
								if ( allAlbumsList.Contains ( tempAlbum ))
								{
									
									Album addToAlbum = allAlbumsList.Find ( Album => Album.name == tempAlbum.name );
									addToAlbum.songs.Add ( tempSong );
									tempSong.album = tempAlbum;
								} else {
									
									tempAlbum.songs.Add ( tempSong );
									allAlbumsList.Add ( tempAlbum );
									tempSong.album = tempAlbum;
								}
								
								UnityEngine.Debug.Log ( tempSong.album.name );
							}
					    break;
						case "Artist":
							if (reader.Read ())
							{
								
								tempArtist = new Artist ( reader.Value.Trim (), new List<Song> ());
								
								if ( allArtistsList.Contains ( tempArtist ))
								{
									
									Artist addToArtist = allArtistsList.Find ( Artist => Artist.name == tempArtist.name );
									addToArtist.songs.Add ( tempSong );
									tempSong.artist = tempArtist;
								} else {
									
									tempArtist.songs.Add ( tempSong );
									allArtistsList.Add ( tempArtist );
									tempSong.artist = tempArtist;
								}
								
								UnityEngine.Debug.Log ( tempSong.artist.name );
							}
					    break;
						case "Genre":
							if (reader.Read ())
							{
								
								tempGenre = new Genre ( reader.Value.Trim (), new List<Song> ());
						
								if ( allGenresList.Contains ( tempGenre ))
								{
									
									Genre addToGenre = allGenresList.Find ( Genre => Genre.name == tempGenre.name );
									addToGenre.songs.Add ( tempSong );
									tempSong.genre = tempGenre;
								} else {
									
									tempGenre.songs.Add ( tempSong );
									allGenresList.Add ( tempGenre );
									tempSong.genre = tempGenre;
								}
								
								UnityEngine.Debug.Log ( tempSong.genre.name );
							}
					    break;
						case "Format":
							if (reader.Read())
							{
						
								tempSong.format = reader.Value.Trim();
								UnityEngine.Debug.Log ( tempSong.format );
							}
					    break;
						case "Download":
							if (reader.Read())
							{
						
								tempSong.downloadLink = reader.Value.Trim();
								UnityEngine.Debug.Log ( tempSong.downloadLink );
							}
					    break;
						case "Link":
							if (reader.Read())
							{
								
//								reader.MoveToAttribute ( 0 );
								UnityEngine.Debug.Log ( "1 " + reader.ReadAttributeValue ());
//								reader.MoveToElement(); 
								UnityEngine.Debug.Log ( "2 " + reader.Value );
/*
								reader.MoveToAttribute( 0 );
								UnityEngine.Debug.Log ( "3 " + reader.Name);
								UnityEngine.Debug.Log ( "4 " + reader.Value);
								reader.MoveToElement(); 
	*/							
								UnityEngine.Debug.Log ( "Read Attribute" );
/*								reader.MoveToAttribute ( 0 );
								UnityEngine.Debug.Log ( "Moved to attribute" );
								
								UnityEngine.Debug.Log ( "Attributes of <" + reader.GetAttribute ( 0 ) + ">" );
*/						
							//	tempSong.supportLinks.Add ( reader.Value.Trim ());
							//	tempSong.supportLinkNames.Add ( reader.Name.Trim ());
								
							//	UnityEngine.Debug.Log ( tempSong.supportLinks.Count ());
							}
						break;
						case "Release":
							if (reader.Read())
							{
						
								tempSong.releaseDate = reader.Value.Trim();
								UnityEngine.Debug.Log ( tempSong.releaseDate );
							}
						break;
				    }
				}
			}
		}
		
		UnityEngine.Debug.Log ( "Done" );
		
		allSongsList.Sort (( a, b ) => a.name.CompareTo ( b.name ));
		allAlbumsList.Sort (( a, b ) => a.name.CompareTo ( b.name ));
		allArtistsList.Sort (( a, b ) => a.name.CompareTo ( b.name ));
		allGenresList.Sort (( a, b ) => a.name.CompareTo ( b.name ));
//		allRecentList.Reverse ();

		specificSort = allRecentList;
		currentPlace = "Recent";
		
		paneManager.loading = false;
		
		if ( paneManager.currentPane == PaneManager.pane.onlineMusicBrowser )
		{
			
			musicViewer.tempEnableOMB = 1.0F;
			startupManager.ombEnabled = true;
		}
	}

Sorry for pasting so much unnecessary code!

Thanks for taking the time to read this!
Gibson

You appear to be doing this the (very) hard way!

If you are trying to read an XML structure into classes you should use XmlSerializer then you can just decorate your target classes with attributes to explain where the data should come from:

  public class SomeXmlClass {
        [XmlAttribute]
        public string someAttribute;
        [XmlElement]
        public string someElement;
        [XmlElement("aDifferentName")]
        public int classNameForIt;
        [XmlElement]
        public SomeOtherClass[] child;
  }

There’s a bunch of other’s but it’s pretty easy - then you just deserialize you entire object hierarchy.

Hio! I just drafted this really quick to iterate through an XML file. It worked for me, though I coded it in javascript maybe you’ll see something you’re missing? (e.g., “using System.Xml”)

import System.Xml;
function readXML(){
var xml = new XmlDocument();
var xmlString : TextAsset = Resources.Load("downloads.xml") as TextAsset; //I'm importing it through resources, you can get the file however you'd like
 	var reader:XmlTextReader = new XmlTextReader(new StringReader(xmlString.text));
 	while(reader.Read()){
		if(reader.Name == "Name") Debug.Log("It's a name!");
	}

}