Reputation: 7823
I need help converting DataTable to XML. I have done it using LINQ but I can't get exactly as I have to. I made a picture so that you can easily understand. The XML needs to be in certain format like below so I can't just use dt.writexml(). Artist ID needs to auto number. Songs are groupped by Artist. Prefer a solution in Linq coz that's what I have used throughout the project but I coundn't manage to get what I want here. The columns names are known so you can use something like this in the code. row.Field(Of String)("title")
Thanks a lot . I mean it. Sorry for poor english.
CreateDatatable - this simple code should create a datatable
Dim dTable As New DataTable
dTable.Columns.Add("Title")
dTable.Columns.Add("Artist")
dTable.Columns.Add("Album")
dTable.Rows.Add("Baby one more time", "Britney Spears", "Baby one more time")
dTable.Rows.Add("Crazy", "Britney Spears", "Best of")
dTable.Rows.Add("Every time", "Britney Spears", "Best of")
dTable.Rows.Add("Black and White", "Michael Jackson", "Best of")
dTable.Rows.Add("You are not alone", "Michael Jackson", "Best of")
dTable.Rows.Add("Smile", "Michael Jackson", "Best of")
what I have at the moment. It will convert it datatable to xml without the groupping and album index.
Dim xmlDoc As New XDocument(
From row In dt.Rows
Select XElement("SONG",
From column In dt.Columns
Select
New XAttribute(column.Name, row.Item(column.Name))
)
)
well .. i also have some more code .. that will query first created xml and do the grouping but still having album="albumname" in the song element as attribute. And it should be just one query from datatable to xml .. i hate having to query against xml again to just refomat it.
Dim replacement = New XDocument(New XElement("root",
original.Descendants("Song")
.GroupBy(Function(x) Convert.ToString(x.Element("artist").value))
.[Select](Function(songsForArtist, index)
New XElement("artist", New XAttribute("id", index + 1),
New XAttribute("name", songsForArtist.Key), songsForArtist))))
Upvotes: 2
Views: 4583
Reputation: 1329
I hope you can convert it to VB.NET
using System;
using System.Linq;
using System.Data;
using System.Xml.Linq;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
var dTable = new DataTable();
dTable.Columns.Add("Title");
dTable.Columns.Add("Artist");
dTable.Columns.Add("Album");
dTable.Rows.Add("Baby one more time", "Britney Spears", "Baby one more time");
dTable.Rows.Add("Crazy", "Britney Spears", "Best of");
dTable.Rows.Add("Every time", "Britney Spears", "Best of");
dTable.Rows.Add("Black and White", "Michael Jackson", "Best of");
dTable.Rows.Add("You are not alone", "Michael Jackson", "Best of");
dTable.Rows.Add("Smile", "Michael Jackson", "Best of");
var query = dTable.AsEnumerable().
GroupBy(row => row.Field<string>("Artist")).
Select(
(grp, i) => new XElement("Artist",
new XAttribute("ID", i + 1),
new XAttribute("ARTISTNAME", grp.Key),
grp.Select(song => new XElement("SONG",
new XAttribute("artistID", i + 1),
new XAttribute("title", song.Field<string>("Title")),
new XAttribute("album", song.Field<string>("Album"))
)
)
)
);
var xml = new XElement("Music", query);
}
}
}
Upvotes: 1
Reputation: 14755
you can use the dotnet typed dataset for this. the dataset has methods to load and save its content from/to xml.
this xsd will give you the desired xml-format with autoincrement id-s nested subtable and xml-attributes instead of xml-elements for the tablefields.
add this to you project and generate a typed dataset out of it.
<xs:schema id="Music" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:msprop="urn:schemas-microsoft-com:xml-msprop">
<xs:element name="Music" msdata:IsDataSet="true" msdata:Locale="en-US">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Artist">
<xs:complexType>
<xs:sequence>
<xs:element name="Song" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:appinfo>
<msdata:Relationship name="SongsOfArtist" msdata:parent="Artist" msdata:child="Song" msdata:parentkey="ID" msdata:childkey="artistid" msprop:Generator_UserRelationName="SongsOfArtist" msprop:Generator_RelationVarName="relationSongsOfArtist" msprop:Generator_UserChildTable="Song" msprop:Generator_UserParentTable="Artist" /></xs:appinfo></xs:annotation>
<xs:complexType>
<xs:attribute name="SongID" msdata:AutoIncrement="true" msdata:AutoIncrementSeed="1" type="xs:long" msdata:AllowDBNull="false" use="prohibited" />
<xs:attribute name="artistid" msdata:AutoIncrementSeed="1" type="xs:long" use="required" />
<xs:attribute name="title" msprop:DateTimeMode="UnspecifiedLocal" type="xs:string" />
<xs:attribute name="album" msprop:DateTimeMode="UnspecifiedLocal" type="xs:string" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="ID" msdata:AutoIncrement="true" msdata:AutoIncrementSeed="1" type="xs:long" use="required" />
<xs:attribute name="ARTISTNAME" msprop:DateTimeMode="UnspecifiedLocal" type="xs:string" />
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:unique name="Song_Constraint1" msdata:ConstraintName="Constraint1">
<xs:selector xpath=".//Song" />
<xs:field xpath="@SongID" />
</xs:unique>
<xs:unique name="Constraint2">
<xs:selector xpath=".//Song" />
<xs:field xpath="@artistid" />
</xs:unique>
<xs:unique name="Constraint1">
<xs:selector xpath=".//Artist" />
<xs:field xpath="@ID" />
</xs:unique>
<xs:keyref name="SongsOfArtist" refer="Constraint1" msdata:IsNested="true">
<xs:selector xpath=".//Song" />
<xs:field xpath="@artistid" />
</xs:keyref>
</xs:element>
</xs:schema>
i am not shure if the vs2010 xsd editor still supports all xsd-settings in this file. Maybes some settings get lost if you edit it with vs 2010. with vs2003-xsd editor it works.
Upvotes: 0