Stuck on problem using Serialization

  • Thread starter Thread starter David Elliott
  • Start date Start date
D

David Elliott

This is what I have produced so far...

<?xml version="1.0" encoding="utf-8"?>
<Database xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Tables>
<Table>
<NameOfTable>Table</NameOfTable>
<Columns>
<Column Name="Col_1">New_Col_1</Column>
<Column Name="Col_2">New_Col_2</Column>
<Column Name="Col_3">New_Col_3</Column>
<Column Name="Col_4">New_Col_4</Column>
<Column Name="Col_5">New_Col_5</Column>
</Columns>
</Table>
</Tables>
</Database>

I want
<NameOfTable>Table</NameOfTable>
in the form of
<NameOfTable Name="Table">NewTableName</NameOfTable>
and am having difficultly doing so.

I can get the form that I am looking for with the Columns because it is
an ArrayList. The NameOfTable is not. It is just a single Element.

Here is the code that produced the results above. I am attempting to
add in the TableName class to solve this problem but am not having
any luck in getting it to print out. It never hits the getter.

Any help is appreciated.
Dave



[XmlInclude(typeof(TableName))]
public class DatabaseTable
{
private TableName tableName;
private string name;
private string className;
private ArrayList columns = new ArrayList();

[XmlElement]
public string NameOfTable
{
get { return (name); }
set { name = value.Trim(); }
}

[XmlArray(ElementName = "Columns")]
[XmlArrayItem(ElementName = "Column", Type = typeof(DatabaseTableColumn))]
public ArrayList Columns
{
get {return (columns); }
}

[XmlElement(Type = typeof(TableName))]
public TableName MyTableName
{
get {return (tableName); }
}
}


public class TableName
{
private string dbName;
private string newName;

public TableName()
{
}

[XmlAttribute]
public string Name
{
get { return (newName); }
set { newName = value.Trim(); }
}

[XmlText(Type=typeof(string))]
public string NameOfDbColumn
{
get { return (dbName); }
set { dbName = value.Trim(); }
}
}
 
David Elliott said:
This is what I have produced so far...

I want
<NameOfTable>Table</NameOfTable>
in the form of
<NameOfTable Name="Table">NewTableName</NameOfTable>
and am having difficultly doing so.

I can get the form that I am looking for with the Columns because it is
an ArrayList. The NameOfTable is not. It is just a single Element.

Well, you *have* specified [XmlElement] for it. Have you tried changing
it to [XmlAttribute("Name")]?
 
Jon,

If I changed it to
[XmlElement("Name")]
public string NameOfTable
{
get { return (name); }
set { name = value.Trim(); }
}

That would get me

<Tables>
<Table>
<Name>Table</Name> <=========================
<Columns>
<Column Name="Col_1">New_Col_1</Column>


The problem is that I have a 2 class fields that I want as 1 XmlElement
Turn this
string field 1 = "Table"
string field 2 = "NewTableName"

Into this
<NameOfTable Name="Table">NewTableName</NameOfTable>

In my attempt to solve this problem, I did 2 things:
1) Remove this property
public string NameOfTable

2) Create a new class and annotate it with XML.

public class TableName
{
private string dbName;
private string newName;

public TableName()
{
}

[XmlAttribute]
public string Name
{
get { return (newName); }
set { newName = value.Trim(); }
}

[XmlText(Type=typeof(string))]
public string NameOfDbColumn
{
get { return (dbName); }
set { dbName = value.Trim(); }
}
}

This new class never gets output.

Cheers,
Dave


David Elliott said:
This is what I have produced so far...

I want
<NameOfTable>Table</NameOfTable>
in the form of
<NameOfTable Name="Table">NewTableName</NameOfTable>
and am having difficultly doing so.

I can get the form that I am looking for with the Columns because it is
an ArrayList. The NameOfTable is not. It is just a single Element.

Well, you *have* specified [XmlElement] for it. Have you tried changing
it to [XmlAttribute("Name")]?
 
Sorry,

Changing it to
[XmlAttribute("Name")]
public string NameOfTable
{
get { return (name); }
set { name = value.Trim(); }
}
Results:

<Tables>
<Table Name="Table">
<Columns>
<Column Name="Col_1">New_Col_1</Column>
<Column Name="Col_2">New_Col_2</Column>
<Column Name="Col_3">New_Col_3</Column>


Looking For:

<Tables>
<Table>
<NameOfTable Name="Table">NewTableName</NameOfTable>
<Columns>
<Column Name="Col_1">New_Col_1</Column>


Cheers,
Dave
Dave

David Elliott said:
If I changed it to
[XmlElement("Name")]

That's not what I suggested though. I suggested

[XmlAttribute("Name")]
 
David Elliott said:
Changing it to
[XmlAttribute("Name")]
public string NameOfTable
{
get { return (name); }
set { name = value.Trim(); }
}
Results:

<Tables>
<Table Name="Table">
<Columns>
<Column Name="Col_1">New_Col_1</Column>
<Column Name="Col_2">New_Col_2</Column>
<Column Name="Col_3">New_Col_3</Column>


Looking For:

<Tables>
<Table>
<NameOfTable Name="Table">NewTableName</NameOfTable>
<Columns>
<Column Name="Col_1">New_Col_1</Column>

Ah. In that case, having the extra class is probably the way to go -
but you didn't show enough code in your sample to really find out
what's wrong.

Could you post a short but complete program which demonstrates the
problem?

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by that.
 
You can drop this code into 1 class file for a console and compile. It will dump
out the file to <project>\bin\debug\output.xml

==================================================================

using System;
using System.IO;
using System.Xml;
using System.Text;
using System.Diagnostics;
using System.Collections;
using System.Xml.Serialization;


namespace XmlFile_5
{
public class MyMain
{
[STAThread]
static void Main(string[] args)
{
DatabaseTable table = null;
DatabaseMapping db = new DatabaseMapping("MyImportantTable");


// Table 0
table = db.AddTable("Table", "New Table Name 0");
table.AddColumn("Col_1", "New_Col_1");
table.AddColumn("Col_2", "New_Col_2");
table.AddColumn("Col_3", "New_Col_3");
table.AddColumn("Col_4", "New_Col_4");
table.AddColumn("Col_5", "New_Col_5");
MyMain.Save(db, "output.xml");
db = null;
}

static public void Save(DatabaseMapping db, string fileName)
{
TextWriter txtWriter = null;
XmlSerializer xmlSerializer = null;
Type objType = null;


try
{
objType = db.GetType();
xmlSerializer = new XmlSerializer(objType);
txtWriter = new StreamWriter(fileName);

xmlSerializer.Serialize(txtWriter, db);
}
catch(Exception ex)
{
Trace.WriteLine(ex.Message);
}
finally
{
// Close The Reader
if (txtWriter != null)
txtWriter.Close();
}
}
}

// ////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////
[XmlInclude(typeof(DatabaseTable))]
public class DatabaseMapping
{
private string name;
private ArrayList dbTable = new ArrayList();

public DatabaseMapping()
{
}

public DatabaseMapping(string dbObjectName)
{
name = dbObjectName;
}


public string DbObjectName
{
get { return (name); }
}

[XmlArray(ElementName = "Tables")]
[XmlArrayItem("Table", Type = typeof(DatabaseTable))]
public ArrayList Tables
{
get {return (dbTable); }
}

public DatabaseTable AddTable(string nameOfDbTable, string newTableName)
{
DatabaseTable table;

table = FindTable(nameOfDbTable);
if (table == null)
{
table = new DatabaseTable(nameOfDbTable, newTableName);
dbTable.Add(table);
}

return (table);
}

public DatabaseTable FindTable(string nameOfDbTable)
{
string tempName = nameOfDbTable.Trim().ToLower();

foreach (DatabaseTable table in dbTable)
{
if (table.NameOfTable.ToLower().Equals(tempName))
return (table);
}

return (null);
}
}

// ////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////
public class DatabaseTable
{
private TableName tableName;
private string name;
private string className;
private ArrayList columns = new ArrayList();


public DatabaseTable(string nameOfDbTable, string newTableName)
{
name = nameOfDbTable.Trim();
className = newTableName.Trim();

tableName = new TableName(nameOfDbTable, newTableName);
}

public DatabaseTable()
{
}

/// <summary>
/// This will be removed when the next property works
/// </summary>
public string NameOfTable
{
get { return (name); }
set { name = value.Trim(); }
}

/// <summary>
/// This will replace the previous property
/// </summary>
[XmlElement(ElementName = "Dave", Type = typeof(TableName))]
public TableName MyTableName
{
get {return (tableName); }
}

/// <summary>
/// This was for testing will ultimately be removed
/// </summary>
[XmlIgnore]
public string NewTableName
{
get { return (className); }
set { className = value.Trim(); }
}

[XmlArray(ElementName = "Columns")]
[XmlArrayItem(ElementName = "Column", Type = typeof(DatabaseTableColumn))]
public ArrayList Columns
{
get {return (columns); }
}

public DatabaseTableColumn AddColumn(string nameOfDbColumn, string nameOfClassColumn)
{
DatabaseTableColumn col;

col = FindColumn(nameOfDbColumn);
if (col == null)
{
col = new DatabaseTableColumn(nameOfDbColumn, nameOfClassColumn);
columns.Add(col);
}

return (col);
}

public DatabaseTableColumn FindColumn(string nameOfDbColumn)
{
string tempName = nameOfDbColumn.Trim().ToLower();

foreach (DatabaseTableColumn col in columns)
{
if (col.Name.ToLower().Equals(tempName))
return (col);
}

return (null);
}
}

// ////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////
public class DatabaseTableColumn
{
private string dbColumn;
private string classColumnName;


public DatabaseTableColumn()
{
}

public DatabaseTableColumn(string nameOfDbColumn, string nameOfClassColumn)
{

dbColumn = nameOfDbColumn.Trim();
classColumnName = nameOfClassColumn.Trim();
}


[XmlAttribute]
public string Name
{
get { return (dbColumn); }
set { dbColumn = value.Trim(); }
}

[XmlText(Type=typeof(string))]
public string NewColumnName
{
get { return (classColumnName); }
set { classColumnName = value.Trim(); }
}
}


// ////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////
public class TableName
{
private string dbName;
private string newName;


public TableName()
{
}

/// <summary>
///
/// </summary>
/// <param name="nameOfDbColumn"></param>
/// <param name="nameOfClassColumn"></param>
public TableName(string nameOfDbTable, string newTableName)
{

dbName = nameOfDbTable.Trim();
newName = newTableName.Trim();
}

[XmlAttribute]
public string Name
{
get { return (newName); }
set { newName = value.Trim(); }
}

[XmlText(Type=typeof(string))]
public string NameOfDbColumn
{
get { return (dbName); }
set { dbName = value.Trim(); }
}
}
}
 
David Elliott said:
You can drop this code into 1 class file for a console and compile.
It will dump out the file to <project>\bin\debug\output.xml

<snip>

Thanks. I've found the problem - your TableName property had a getter
but no setter, which apparently means it doesn't get serialized
(presumably because it couldn't be deserialized).

Just adding a setter makes it work fine.
 
Back
Top