现在我开始说这确实是一种贬义。然而,我几乎完成了它,直到我遇到了Linq to XML语法。
我有2个类:Track和CD现在作为分配的一部分我创建了一个CD,然后添加了一些轨道。在搜索了很多完全解释如何从xml到对象的教程之后,我似乎无法将其工作(对象为xml)。
我目前有:
//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);
现在这就是我需要将其放入XML的对象。 to XML部分是:
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);
这个效果很好(得到我需要的结果!)仅1 cd。当我决定添加另一张CD时,它会显示:
An unhandled exception of type 'System.InvalidOperationException' occurred in System.Xml.Linq.dll
Duplicate Attribute (cd)
指向XDocument。除了这不工作之外它感觉非常愚蠢(来自cds x2中的c)但是无论我尝试什么,我似乎无法阻止这种语法来讨厌我:
(
from c in cds
select new XAttribute("artist",c.getArtist()),
select new XAttribute("name", c.getTitle()) //No not happening!
),
对您提供的任何帮助都会非常满意!
答案 0 :(得分:7)
首先,我建议您使用属性和C#样式命名方法。以下是您的类可以重构的方式:
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;
}
}
这是Value Object类 - 私有的setter不允许更改此类之外的属性值。这里是轨道课程:
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; }
}
现在您可以使用Fluent API创建CD集合:
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))
};
这是XML创建:
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)));
这里有几个问题 - 缺少根节点,并在每次迭代时枚举所有CD。
答案 1 :(得分:3)
您的XDocument构造存在一些问题。
试试这个(原谅我把你的getter / setter变成属性:
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))))));
答案 2 :(得分:1)
select new XElement("cd", /*From new to the end of this is the error*/
(
from c in cds
select new XAttribute("artist",c.getArtist())
),
这将创建一个名为cd
的元素(这很好),但是然后尝试为集合中的每张CD添加一个artist
属性,这几乎可以肯定不是你想要的,而是问题的原因。
也就是说,这段代码试图像这样制作xml:
<cd
artist="Dream Theater"
artist="TestArtist"
// the later stuff
您可能知道的是非法的xml。
你缺少的想法是:
(from cl in cds orderby cl.getArtist()
您正在使用LINQ为您执行循环 - 在from
的范围内,c1
来自集合的一张特定CD。因此,您不需要在此中执行from c in cds
,因为您已经拥有了所需的CD
对象:
select new XElement("cd", /*From new to the end of this is the error*/
select new XAttribute("artist",c1.getArtist()),
select new XAttribute("name", c1.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())
)
)
)
)
)
您在选择c1.getTracks()
时已经有了正确的想法;在创建属性时应用相同的想法。