I am looking for a way to convert an object tree to XML. It would be fun to write, but I am sure someone has already written it. Here is my wish list:
I don't need to reconstruct the object model, so a write-only solution is fine (probably expected).
I think that discounts:
C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...
In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.
C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.
What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.
Robert Rossney's post made me think it's probably less work than I thought. So here's a very rough attempt. It handles the following:
Here's an example of the output (in my test objects, the "Currency" product on the Order throws an exception).
<Customer Ref="1">
<FirstName>Paul</FirstName>
<LastName>Stovell</LastName>
<FullName>Paul Stovell</FullName>
<Orders>
<Order Ref="2">
<SKU>Apples</SKU>
<Price>27.30</Price>
<Currency>Something bad happened</Currency>
<Customer Ref="1" />
</Order>
<Order Ref="3">
<SKU>Pears</SKU>
<Price>17.85</Price>
<Currency>Something bad happened</Currency>
<Customer Ref="1" />
</Order>
<Order Ref="2" />
</Orders>
</Customer>
Here's the sample object model and usage:
static void Main(string[] args)
{
var customer = new Customer();
customer.FirstName = "Paul";
customer.LastName = "Stovell";
customer.Orders.Add(new Order(customer) { Price = 27.30M, SKU = "Apples"});
customer.Orders.Add(new Order(customer) { Price = 17.85M, SKU = "Pears"});
customer.Orders.Add(customer.Orders[0]);
var output = new StringWriter();
var writer = new XmlTextWriter(output);
writer.Formatting = Formatting.Indented;
WriteComplexObject("Customer", customer, writer);
Console.WriteLine(output.ToString());
Console.ReadKey();
}
class Customer
{
private readonly List<Order> _orders = new List<Order>();
public Customer()
{
}
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName
{
// Read-only property test
get { return FirstName + " " + LastName; }
}
public List<Order> Orders
{
// Collections test
get { return _orders; }
}
}
class Order
{
private readonly Customer _customer;
public Order(Customer customer)
{
_customer = customer;
}
public string SKU { get; set; }
public decimal Price { get; set; }
public string Currency
{
// A proprty that, for some reason, can't be read
get
{
throw new Exception("Something bad happened");
}
}
public Customer Customer
{
get { return _customer; }
}
}
Here's the implementation:
public static void WriteObject(string name, object target, XmlWriter writer)
{
WriteObject(name, target, writer, new List<object>(), 0, 10, -1);
}
private static void WriteObject(string name, object target, XmlWriter writer, List<object> recurringObjects, int depth, int maxDepth, int maxListLength)
{
var formatted = TryToFormatPropertyValueAsString(target);
if (formatted != null)
{
WriteSimpleProperty(name, formatted, writer);
}
else if (target is IEnumerable)
{
WriteCollectionProperty(name, (IEnumerable)target, writer, depth, maxDepth, recurringObjects, maxListLength);
}
else
{
WriteComplexObject(name, target, writer, recurringObjects, depth, maxDepth, maxListLength);
}
}
private static void WriteComplexObject(string name, object target, XmlWriter writer, List<object> recurringObjects, int depth, int maxDepth, int maxListLength)
{
if (target == null || depth >= maxDepth) return;
if (recurringObjects.Contains(target))
{
writer.WriteStartElement(name);
writer.WriteAttributeString("Ref", (recurringObjects.IndexOf(target) + 1).ToString());
writer.WriteEndElement();
return;
}
recurringObjects.Add(target);
writer.WriteStartElement(name);
writer.WriteAttributeString("Ref", (recurringObjects.IndexOf(target) + 1).ToString());
foreach (var property in target.GetType().GetProperties())
{
var propertyValue = ReadPropertyValue(target, property);
WriteObject(property.Name, propertyValue, writer, recurringObjects, depth + 1, maxDepth, maxListLength);
}
writer.WriteEndElement();
}
private static object ReadPropertyValue(object target, PropertyInfo property)
{
try { return property.GetValue(target, null); }
catch (Exception ex) { return ReadExceptionMessage(ex); }
}
private static string ReadExceptionMessage(Exception ex)
{
if (ex is TargetInvocationException && ex.InnerException != null)
return ReadExceptionMessage(ex.InnerException);
return ex.Message;
}
private static string TryToFormatPropertyValueAsString(object propertyValue)
{
var formattedPropertyValue = null as string;
if (propertyValue == null)
{
formattedPropertyValue = string.Empty;
}
else if (propertyValue is string || propertyValue is IFormattable || propertyValue.GetType().IsPrimitive)
{
formattedPropertyValue = propertyValue.ToString();
}
return formattedPropertyValue;
}
private static void WriteSimpleProperty(string name, string formattedPropertyValue, XmlWriter writer)
{
writer.WriteStartElement(name);
writer.WriteValue(formattedPropertyValue);
writer.WriteEndElement();
}
private static void WriteCollectionProperty(string name, IEnumerable collection, XmlWriter writer, int depth, int maxDepth, List<object> recurringObjects, int maxListLength)
{
writer.WriteStartElement(name);
var enumerator = null as IEnumerator;
try
{
enumerator = collection.GetEnumerator();
for (var i = 0; enumerator.MoveNext() && (i < maxListLength || maxListLength == -1); i++)
{
if (enumerator.Current == null) continue;
WriteComplexObject(enumerator.Current.GetType().Name, enumerator.Current, writer, recurringObjects, depth + 1, maxDepth, maxListLength);
}
}
catch (Exception ex)
{
writer.WriteElementString(ex.GetType().Name, ReadExceptionMessage(ex));
}
finally
{
var disposable = enumerator as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
writer.WriteEndElement();
}
}
I would still be interested to know if there are more tried and tested solutions.
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