Now I will start off by saying this is indeed an assigment. I have however nearly finished it untill I ran into the Linq to XML syntax.
I have 2 classes: Track and CD now as part of the assigment I create a cd and then added some tracks to it. After searching for lots of tutorials that explained perfectly how to go from xml to objects I just cannot seem to get this working (objects to xml).
I currently have:
//My list of cds
List<CD> cds = new List<CD>();
//Make a new CD and add some tracks to it
CD c1 = new CD("Awake","Dream Theater");
Track t1 = new Track("6:00", "Dream Theater", new TimeSpan(00, 05, 31));
Track t2 = new Track("Caught in a Web", "Dream Theater", new TimeSpan(00, 05, 28));
Track t3 = new Track("Innocence Faded", "Dream Theater", new TimeSpan(00, 05, 34));
c1.addTrack(t1);
c1.addTrack(t2);
c1.addTrack(t3);
cds.Add(c1);
//Make another cd and add it
CD c2 = new CD("Second cd","TestArtist");
Track t4 = new Track("TrackForSecond","TestArtist",new TimeSpan(00,13,37));
c2.addTrack(t4);
cds.add(c2);
Now this is what gets me the objects I need to put into XML. The to XML part is:
XDocument xmlOutput = new XDocument (
new XDeclaration("1.0","utf-8","yes"),
(from cl in cds orderby cl.getArtist()
select new XElement("cd", /*From new to the end of this is the error*/
(
from c in cds
select new XAttribute("artist",c.getArtist())
),
(
from c in cds
select new XAttribute("name", c.getTitle())
),
new XElement("tracks",
(
from t in c1.getTracks()
select new XElement("track",
new XElement("artist",t1.getArtist()),
new XElement("title",t1.getTitle()),
new XElement("length",t1.getLength())
)
)
)
)
)
);
Console.WriteLine(xmlOutput);
This works great (gets me the result I need!) for just 1 cd. When I decide to add another cd it shows:
An unhandled exception of type 'System.InvalidOperationException' occurred in System.Xml.Linq.dll
Duplicate Attribute (cd)
Which is pointing at the XDocument. Aside from this not working it feels pretty stupid (from c in cds x2) but whatever I try I cannot seem to stop this syntax from hating me:
(
from c in cds
select new XAttribute("artist",c.getArtist()),
select new XAttribute("name", c.getTitle()) //No not happening!
),
Would be very happy with any help you can provide!
LINQ to XML is a LINQ-enabled, in-memory XML programming interface that enables you to work with XML from within the . NET programming languages. LINQ to XML is like the Document Object Model (DOM) in that it brings the XML document into memory.
XDocument is from the LINQ to XML API, and XmlDocument is the standard DOM-style API for XML. If you know DOM well, and don't want to learn LINQ to XML, go with XmlDocument . If you're new to both, check out this page that compares the two, and pick which one you like the looks of better.
The LINQ to XML will bring the XML document into memory and allows us to write LINQ Queries on in-memory XML document to get the XML document elements and attributes. To use LINQ to XML functionality in our applications, we need to add "System. Xml. Linq" namespace reference.
The XDocument class contains the information necessary for a valid XML document, which includes an XML declaration, processing instructions, and comments. You only have to create XDocument objects if you require the specific functionality provided by the XDocument class.
First, I suggest you to use properties and C# style naming for methods. Here is how your classes could be refactored:
public class CD
{
private readonly List<Track> _tracks = new List<Track>();
public CD(string artist, string title)
{
Artist = artist;
Title = title;
}
public string Artist { get; private set; }
public string Title { get; private set; }
public IEnumerable<Track> Tracks
{
get { return _tracks; }
}
public void AddTrack(Track track)
{
_tracks.Add(track);
}
public CD WithTrack(string title, TimeSpan length)
{
AddTrack(new Track(Artist, title, length));
return this;
}
}
This is Value Object class - private setters does not allow to change property values outside of this class. And here is class for track:
public class Track
{
public Track(string artist, string title, TimeSpan length)
{
Artist = artist;
Title = title;
Length = length;
}
public string Artist { get; set; }
public string Title { get; private set; }
public TimeSpan Length { get; private set; }
}
Now you can use Fluent API to create collection of CDs:
List<CD> cds = new List<CD>
{
new CD("Awake", "Dream Theater")
.WithTrack("6:00", new TimeSpan(00, 05, 31))
.WithTrack("Caught in a Web", new TimeSpan(00, 05, 28))
.WithTrack("Innocence Faded", new TimeSpan(00, 05, 34)),
new CD("Second cd", "TestArtist")
.WithTrack("TrackForSecond", new TimeSpan(00, 13, 37))
};
And here is XML creation:
var xDoc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("cds",
from cd in cds
orderby cd.Artist
select new XElement("cd",
new XAttribute("artist", cd.Artist),
new XAttribute("name", cd.Title),
from t in cd.Tracks
select new XElement("track",
new XElement("artist", t.Artist),
new XElement("title", t.Title),
new XElement("length", t.Length)));
You had several problems here - missing root node, and enumerating over all CDs on each iteration.
There are a few problems with your XDocument construction.
Try this (forgive me for turning your getters/setters into properties:
var xmlOutput = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement(
"cds",
from cd in cds
orderby cd.Artist.ToUpperInvariant()
select new XElement(
"cd",
new XAttribute("title", cd.Title),
new XAttribute("artist", cd.Artist),
new XElement(
"tracks",
from t in cd.Tracks
select new XElement(
"track",
new XAttribute("artist", t.Artist),
new XAttribute("title", t.Title),
new XAttribute("length", t.Length))))));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With