0

I need to generate the following XML, but have thus far been unsuccessful in injecting my custom header data:

<?xml version="1.0" encoding="UTF-8"?>
<ns0:MT_Get_Name_Req xmlns:ns0="http://hsd.sd.com">
   <personnel_id>1202</personnel_id>
   <dob>19470906</dob>
</ns0:MT_Get_Name_Req>

How can i generate the above XML, from within C#?

Currently we have :

    XmlSerializer serializer = new XmlSerializer(typeof(Employee));
    StringWriter sww = new StringWriter();
    XmlWriter writer = XmlWriter.Create(sww);
    serializer.Serialize(writer, employee);

Employee Class:

public class Employee
{
    public string personnel_id { get; set; }
    public string dob { get; set; }
}
jordan
  • 3,436
  • 11
  • 44
  • 75

2 Answers2

0

Making some reasonable guesses about what your Employee class looks like, you need to do the following:

  1. Decorate your Employee class with [XmlRoot("MT_Get_Name_Req", Namespace = "http://hsd.sd.com")]. This will give your XML root element the correct name and namespace.

  2. While the root is in the http://hsd.sd.com namespace, its child elements are not in any namespace. Thus their namespace will need to be overridden using an XmlElement attribute.

  3. Setting the XmlRoot namespace will use the specified namespace as the default namespace. If you must use a prefixed namespace, you need to pass a XmlSerializerNamespaces with all desired namespaces to XmlSerializer.Serialize().

Thus:

[XmlRoot("MT_Get_Name_Req", Namespace = Employee.XmlNamespace)]
public class Employee
{
    public const string XmlNamespace = "http://hsd.sd.com";
    public const string XmlNamespacePrefix = "ns0";

    const string xsi = "http://www.w3.org/2001/XMLSchema-instance";
    const string xsd = "http://www.w3.org/2001/XMLSchema";

    public static XmlSerializerNamespaces XmlSerializerNamespaces
    {
        get
        {
            var namespaces = new XmlSerializerNamespaces();
            namespaces.Add(XmlNamespacePrefix, XmlNamespace);
            // namespaces.Add("xsi", xsi);  Uncomment to add standard namespaces.
            // namespaces.Add("xsd", xsd);
            return namespaces;
        }
    }

    [XmlElement("personnel_id", Namespace="")]
    public string personnel_id { get; set; }

    [XmlElement("dob", Namespace = "")]
    public string dob { get; set; }
}

And use it like

        var xml = XmlSerializationHelper.GetXml(employee, Employee.XmlSerializerNamespaces, Encoding.UTF8);

Using the extension methods:

public static class XmlSerializationHelper
{
    public sealed class StringWriterWithEncoding : StringWriter
    {
        private readonly Encoding encoding;

        public StringWriterWithEncoding(Encoding encoding)
        {
            this.encoding = encoding;
        }

        public override Encoding Encoding
        {
            get { return encoding; }
        }
    }

    public static string GetXml<T>(T obj, XmlSerializerNamespaces ns, Encoding encoding)
    {
        return GetXml(obj, new XmlSerializer(obj.GetType()), ns, encoding);
    }

    public static string GetXml<T>(T obj, XmlSerializer serializer, XmlSerializerNamespaces ns, Encoding encoding)
    {
        using (var textWriter = new StringWriterWithEncoding(encoding))
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;        // For cosmetic purposes.
            settings.IndentChars = "    "; // For cosmetic purposes.
            using (var xmlWriter = XmlWriter.Create(textWriter, settings))
            {
                if (ns != null)
                    serializer.Serialize(xmlWriter, obj, ns);
                else
                    serializer.Serialize(xmlWriter, obj);
            }
            return textWriter.ToString();
        }
    }
}

To get

<?xml version="1.0" encoding="utf-8"?>
<ns0:MT_Get_Name_Req xmlns:ns0="http://hsd.sd.com">
    <personnel_id>1202</personnel_id>
    <dob>19470906</dob>
</ns0:MT_Get_Name_Req>
dbc
  • 104,963
  • 20
  • 228
  • 340
  • Thank you for your answer - just tested and This doesn't spit out the required XML - it adds the W#schools thing to the header and also adds NS0 to all the nodes – jordan Feb 25 '15 at 18:48
  • 1202 19470906 is what i get after removing the w3schools – jordan Feb 25 '15 at 18:49
  • @jordan.peoples - I missed the fact that `personnel_id` and `dob` are in a different namespace than the root element. Updated. – dbc Feb 25 '15 at 18:54
  • @jordan.peoples - `encoding="utf-16"` shows up because your writing to a string not a file, and c# strings are encoded in utf-16. If you want to write to a string but force `utf-8` to appear as the encoding, see here: https://stackoverflow.com/questions/1564718/using-stringwriter-for-xml-serialization/1564727#1564727 – dbc Feb 25 '15 at 18:57
  • @jordan.peoples - 1) you mean the Jon Skeet solution didn't work? 2) Is everything else OK? – dbc Feb 25 '15 at 19:13
  • What i did to get your solution to run correctly, is simply call String.replace on your XML output to replace UTF-16 with UTF-8 and it worked like a charm – jordan Feb 25 '15 at 19:21
  • @jordan.peoples - I just tried the Skeet solution and it seems to work; I updated my answer with the appropriate code. But string.Replace() should be fine also. – dbc Feb 25 '15 at 19:25
  • This feels like the super long confusing way to do it, but it did the trick, hacking together the correct XML. – jordan Feb 25 '15 at 22:54
0

I did a small example for you. I included an XmlRoot Attribute to the Employee.class and added a namespace object when serializing the employee.

Employee.cs

[XmlRoot("MT_Get_Name_Req", Namespace = "http://hsd.sd.com")]
public class Employee
{
    [XmlElement(Namespace="")]
    public string personnel_id { get; set; }
    [XmlElement(Namespace = "")]
    public string dob { get; set; }
}

demoFile.cs

private static void customXmlSerialization()
{
    Employee employee = new Employee() { personnel_id = "1202", dob = "19470906" };
    XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
    ns.Add("ns0", "http://hsd.sd.com");
    XmlSerializer serializer = new XmlSerializer(typeof(Employee));

    string path = @"e:\temp\data.xml";
    XmlTextWriter writer = new XmlTextWriter(path, Encoding.UTF8);
    serializer.Serialize(writer, employee,ns);
}

output

<?xml version="1.0" encoding="utf-8"?>
<ns0:MT_Get_Name_Req xmlns:ns0="http://hsd.sd.com">
  <personnel_id>1202</personnel_id>
  <dob>19470906</dob>
</ns0:MT_Get_Name_Req>
Community
  • 1
  • 1
Pilgerstorfer Franz
  • 8,303
  • 3
  • 41
  • 54