3

I am retrieving a datetime string as "2015-07-16T07:40:35Z".

<?xml version="1.0" encoding="UTF-8"?>
<people type="array">
   <person>
      <last-name>lastName</last-name>
      <first-name>firstName</first-name>
      <id type="integer">123</id>
      <last-changed-on type="date">2014-11-21T15:04:53Z</last-changed-on>
   </person>
</people>

I searched about this problem and found something like below.

[XmlIgnore]
public DateTime Start { get; set; }

[XmlElement("start")]
public string StartDateString
{
    get { return this.Start.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'"); }
    set { this.Start = DateTime.Parse(value); }
}

I want to deserialize that XmlElement to a Datetime property of an object. After that when I serialize that object I want to create a datetime string with format of "2015-07-16T07:40:35Z". So how would i change get/set block of properties for this issue.

3
  • What is the problem with your code? Commented Jul 18, 2015 at 22:08
  • Why are you using ToString()? DateTime.Parse() will work : string input = "2014-11-21T15:04:53Z"; DateTime date = DateTime.Parse(input); Commented Jul 20, 2015 at 12:35
  • I tried to datetime.parse but it didn't work. My last-changed-on element is now comes with type="date" attribute like <last-changed-on type="date">2014-11-21T15:04:53Z</last-changed-on> . Commented Jul 20, 2015 at 13:11

3 Answers 3

7

It looks like the formats you're dealing with are in the standard XML DateTime format. So in this case you don't need a proxy string property to handle it, you can use the built in functionality of the XmlSerializer and specify the dateTime data type on the relevant XmlElement. Update: specifying the dateTime doesn't work if the element is empty (even in combination with isNullable), here is a way to convert the string manually to a DateTime.

For example..

[XmlRoot("person")]
public class Person
{
    [XmlElement("last-name")]
    public string LastName { get; set; }
    [XmlElement("first-name")]
    public string FirstName { get; set; }
    [XmlElement("id")]
    public int Id { get; set; }
    [XmlElement(ElementName = "last-changed-on")]
    public XmlDateTime LastChangedOn { get; set; }
}

Edit: sounds like you have Xml where LastChangedOn can be empty or missing. In this case you can implement a custom class to handle the conversion and keep the Person class clean. I've added implict conversions so you can just treat the property as if it were a DateTime. Above changes slightly to have XmlDateTime instead of DateTime.

[DebuggerDisplay("{Value}")]
public class XmlDateTime : IXmlSerializable
{
    public DateTime Value { get; set; }
    public bool HasValue { get { return Value != DateTime.MinValue; } }
    private const string XML_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZ";

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
        if (reader.IsEmptyElement)
        {
            reader.ReadStartElement();
            return;
        }

        string someDate = reader.ReadInnerXml();
        if (String.IsNullOrWhiteSpace(someDate) == false)
        {
            Value = XmlConvert.ToDateTime(someDate, XML_DATE_FORMAT);
        }
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        if (Value == DateTime.MinValue)
            return;

        writer.WriteRaw(XmlConvert.ToString(Value, XML_DATE_FORMAT));
    }

    public static implicit operator DateTime(XmlDateTime custom)
    {
        return custom.Value;
    }

    public static implicit operator XmlDateTime(DateTime custom)
    {
        return new XmlDateTime() { Value = custom };
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

I changed my attribute to this but I have an exception as "The string '' is not a valid AllXsd value". I think i should some datetime conversion as in my question but i can't find how to do it.
@Yusuf Duyar, Sounds like in your XML the date elements can be empty? See update, for a way to convert to a DateTime that handles this case. Personally, I don't like the idea of using the proxy string property, not very elegant.
thanks for your answer. as you guess another datetime field is can be empty and your solution fixed my problem.
1

Instead of serialization you can use XML linq like this

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string input = 
                "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                "<people type=\"array\">" +
                   "<person>" +
                      "<last-name>lastName</last-name>" +
                      "<first-name>firstName</first-name>" +
                      "<id type=\"integer\">123</id>" +
                      "<last-changed-on>2014-11-21T15:04:53Z</last-changed-on>" +
                   "</person>" +
                "</people>";

            XDocument doc = XDocument.Parse(input);

            var results = doc.Descendants("person").Select(x => new {
                last_name = x.Element("last-name").Value,
                first_name = x.Element("first-name").Value,
                id = int.Parse(x.Element("id").Value),
                last_changed = DateTime.Parse(x.Element("last-changed-on").Value)
            }).ToList();
        }
    }
}
​

1 Comment

I wrote all my classes XmlSerialization based. So it's hard to change them to LINQ queries. But if I can't fix my datetime problem i will unfortunatelly change my method to this.
0

If dont like System.Xml.XmlConvert.ToDateTime(str, "yyyy-MM-dd'T'HH:mm:ssZ")
Can use standart function: DateTime.ParseExact(str, "yyyy-MM-dd'T'HH:mm:ssZ", System.Globalization.CultureInfo.InvariantCulture)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.