Reputation: 89
I need to synchronize between databases with different fieldnames. I can export records to a xml files from the first database as:
<Table>
<Route No="1108">
<Name No="60">Joe</Name>
<City No="70">City1</City>
</Route>
<Route No="1108">
<Name No="60">John</Name>
<City No="70">City2</City>
</Route>
<Route No="1108">
<Name No="60">Jan</Name>
<City No="70">City4</City>
</Route>
<Route No="1108">
<Name No="60">Jack</Name>
<City No="70">City6</City>
</Route>
</Table>
I can serialize this XML file into the second database using the element names Route->Name and City.
But send some data back is the problem. I have declared the class like this:
public class Route
{
[XmlAttribute]
public string No
{
get { return "1108"; }
}
public string Name
{
get { return _Name; }
set { _Name = value; }
}
public string City
{
get { return _City; }
set { _City = value; }
}
}
I can create this in code easily but for 100 tables it's to much work. I would like to use de/serialize?
I would never expected this to be my show stopper.
Upvotes: 0
Views: 1357
Reputation: 89
After reading and reading it I came up with this.
1. I added my own attribute class? there must be a smarter way!!
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = true)]
public class XMLAttributeProperty : Attribute
{
public XMLAttributeProperty(string name, string value)
{
this.Name = name;
Value = value;
}
public string Name;
public string Value;
}
2. Add these attributes to the class properties
public class Route
{
[XmlAttribute]
public string No
{
get { return "1108"; }
}
**[XMLAttributeProperty("No", "60")]**
public string Name
{
get { return _Name; }
set { _Name = value; }
}
**[XMLAttributeProperty("No", "70")]**
public string City
{
get { return _City; }
set { _City = value; }
}
}
3. After the default serializing the class to an element..
<Table>
<Route No="1108">
<Name>Joe</Name>
<City>City1</City>
</Route>
</Table>
4. I take over and add the attributes.
foreach (var property in trp.GetType().GetProperties()) //class ->typeof(Transport).GetProperties()
{
foreach (XMLAttributeProperty att in property.GetCustomAttributes(typeof(XMLAttributeProperty), true).Cast<XMLAttributeProperty>())
{
Log.Level0(string.Format("Property {0}, {1}={2}", property.Name, att.Name, att.Value));
var fieldInElement = el.Descendants(property.Name).FirstOrDefault();
if (fieldInElement != null)
{
try
{
fieldInElement.Add(new XAttribute(att.Name, att.Value));
}
catch { }
}
}
}
5. This is the result. Please comment or show me a better/faster way. Im happy but lost a lot of time.
<Table>
<Route No="1108">
<Name No="60">Joe</Name>
<City No="70">City1</City>
</Route>
</Table>
Upvotes: 0
Reputation: 1246
How about this?
public class Route
{
[XmlAttribute("No")]
public int Number { get {return "1108";} }
public Name Name { get; set; }
public City City { get; set; }
}
public class Name
{
[XmlAttribute("No")]
public int Number { get {return "60";} }
[XmlText]
public string Value { get; set; }
}
public class City
{
[XmlAttribute("No")]
public int Number { get {return "70";} }
[XmlText]
public string Name { get; set; }
}
Upvotes: 0
Reputation: 292695
John Saunders is right, XML serialisation is probably not the best tool for the job...
Now, if you still want to go this way, there are two options if you want to add attributes on Name
and City
:
Implement the IXmlSerializable
interface, which gives you full control over the XML serialization process. The major drawback is that it's tedious to implement, especially if you must do it for many classes
Make classes for Name
and City
, rather than represent them directly as strings. Since there seems to be a No
attribute on all you elements, you might as well make them all inherit from a common base class. You can use the XmlText
attribute to serialize a property as the content of an element.
public abstract class EntityWithNumber
{
[XmlAttribute("No")]
public int Number { get; set; }
}
public class Name : EntityWithNumber
{
[XmlText]
public string Value { get; set; }
}
public class City : EntityWithNumber
{
[XmlText]
public string Name { get; set; }
}
public class Route : EntityWithNumber
{
public Name Name { get; set; }
public City City { get; set; }
}
Upvotes: 1
Reputation: 11587
Actually I think you need something different altogether.
From the snippet you provided, I guess you could deserialize in an object like this:
[Serializable]
[XmlType(AnonymousType=true)]
[XmlRoot(IsNullable=false)]
public partial class Table {
[XmlElement("Route")]
public TableRoute[] Items { get; set; }
}
}
[Serializable]
[XmlType(AnonymousType=true)]
public partial class TableRoute {
[XmlElement]
public TableRouteItem[] Name { get; set; }
[XmlElement]
public TableRouteItem[] City { get; set; }
[XmlAttribute]
public string No { get; set; }
}
[Serializable]
[XmlType(AnonymousType=true)]
public partial class TableRouteItem {
[XmlAttribute]
public string No { get; set; }
[XmlText]
public string Value { get; set; }
}
The problem with your data is that the columns (or what I guess are columns) there are more than one value per item.
Upvotes: 0
Reputation: 424
While setting XMLAttribute attribute you can only add attribute to root XML element.
Upvotes: 0
Reputation: 161831
You seem to have chosen the wrong tool for the job.
This is a job for SQL Server Integration Services (SSIS). This is exactly what it's good at.
Upvotes: 1