KF-SoftwareDev
KF-SoftwareDev

Reputation: 403

Generate XML from C# Class with specific attributes

I am stuck with an issue regarding XML serialization of a class in c#: What i Want is the XML in the format below

<?xml version="1.0" encoding="utf-8"?>
<MyClass:Req xsi:schemaLocation="http://www.Test.com/MyClass.xsd"
            xmlns:TestClass="http://www.Test.com/MyClass" 
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns="http://www.Test.com/MyClass">
  <head>
    <hA>01</hA>
  </head>
  <body>
    <R1>0</R1>
    <R3 />
    <R4 />
  </body>
</MyClass:Req>

All the XMLNS attributes are required and need to be configure via the code. The output i am currently getting is:

<?xml version="1.0" encoding="utf-8"?>
<MyClass_x003A_Req xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns="http://www.Test.com/MyClass">
  <head>
    <hA>01</hA>
  </head>
  <body>
    <R1>0</R1>
    <R3 />
    <R4 />
  </body>
</MyClass_x003A_Req>

As you can see the line containing the prolog is incorrect, i need it to show just the values in the first XML example. Also the Colon is transformed to x003A and i need this to be a COLON.

Here is the code i am using at the moment, bear in mind its just test code the fields are to be changed before production.

request theReq = new request();
requestHead rHead = new requestHead();
requestBody rBody = new requestBody();

rHead.hA = "01";

rBody.R1 = "0";

theReq.head = rHead;
theReq.body = rBody;

XmlSerializer serializer = new XmlSerializer(typeof(request));
TextWriter textWriter = new StreamWriter(@"Test.xml");
serializer.Serialize(textWriter, theReq);
textWriter.Close();




[XmlRoot(Namespace = "http://www.Test.com/MyClass",
    ElementName = "MyClass:Req",
    DataType = "string",
    IsNullable = true)]
public partial class request
{
    private requestHead headField;

    private requestBody bodyField;

    public request()
    {
        this.bodyField = new requestBody();
        this.headField = new requestHead();
    }

    public requestHead head
    {
        get
        {
            return this.headField;
        }
        set
        {
            this.headField = value;
        }
    }

    public requestBody body
    {
        get
        {
            return this.bodyField;
        }
        set
        {
            this.bodyField = value;
        }
    }
}

public partial class requestHead
{
    private string headAField;

    private string headBField;

    public string hA
    {
        get
        {
            return this.headAField;
        }
        set
        {
            this.headAField = value;
        }
    }

    public string hB
    {
        get
        {
            return this.headBField;
        }
        set
        {
            this.headBField = value;
        }
    }
}

public partial class requestBody
{
    private string R1Field;

    private string R2Field;

    private requestBodyR3 R3Field;

    private requestBodyR4 R4Field;

    public requestBody()
    {
        this.R4Field = new requestBodyR4();
        this.R3Field = new requestBodyR3();
    }

    public string R1
    {
        get
        {
            return this.R1Field;
        }
        set
        {
            this.R1Field = value;
        }
    }

    public string R2
    {
        get
        {
            return this.R2Field;
        }
        set
        {
            this.R2Field = value;
        }
    }

    public requestBodyR3 R3
    {
        get
        {
            return this.R3Field;
        }
        set
        {
            this.R3Field = value;
        }
    }

    public requestBodyR4 R4
    {
        get
        {
            return this.R4Field;
        }
        set
        {
            this.R4Field = value;
        }
    }
}

public partial class requestBodyR3
{

    private string R31Field;

    private string R32Field;

    public string R31
    {
        get
        {
            return this.R31Field;
        }
        set
        {
            this.R31Field = value;
        }
    }

    public string R32
    {
        get
        {
            return this.R32Field;
        }
        set
        {
            this.R32Field = value;
        }
    }
}

public partial class requestBodyR4
{
    private string R41Field;

    public string R41
    {
        get
        {
            return this.R41Field;
        }
        set
        {
            this.R41Field = value;
        }
    }
}

I understand that i need to change the XMLRoot line to achive the desired output but i am unsure what i need to change here?

Also how do i force the COLON to be preserved and not modified to the x003A before its written to the file.

One final question since i do not populate R3 & R4 is there a way i can prevent them being written to the XML if there values are not populated similar to the way R2 is not written to the file, i believe the difference is that R2 is a string and R3 & R4 are complex types making it more difficult for the serializer to determine if they should be wrote?

EDIT:

OK after applying Ralp's suggested changes the file now looks like:

<?xml version="1.0" encoding="utf-8"?>
<MyClass:Req d1p1:schemaLocation="http://www.test.com/myclass.xsd" 
             xmlns:d1p1="http://www.w3.org/2001/XMLSchema-instance" 
             xmlns:MyClass="http://www.test.com/myclass">
  <head>
    <hA>01</hA>
  </head>
  <body>
    <R1>0</R1>
    <R3 />
    <R4 />
  </body>
</MyClass:Req>

How can I change the d1p1 for xsi?

Also the one line that's missing is xmlns="http://www.Test.com/MyClass">, how do i add that in?

EDIT - 2:

Almost there thanks to Ralp's help, here is the updated file:

<?xml version="1.0" encoding="utf-8"?>
<MyClass:Req xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
             xsi:schemaLocation="http://www.test.com/myclass.xsd" 
             xmlns:MyClass="http://www.test.com/myclass">
  <head>
    <hA>01</hA>
  </head>
  <body>
    <R1>0</R1>
    <R3 />
    <R4 />
  </body>
</MyClass:Req>

And updated CODE:

request theReq = new request();
requestHead rHead = new requestHead();
requestBody rBody = new requestBody();

rHead.hA = "01";

rBody.R1 = "0";

theReq.head = rHead;
theReq.body = rBody;

XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");
ns.Add("MyClass", "http://www.test.com/myclass");

XmlSerializer serializer = new XmlSerializer(typeof(request));
TextWriter textWriter = new StreamWriter(@"Test.xml");
serializer.Serialize(textWriter, theReq, ns);
textWriter.Close();



[XmlRoot(Namespace = "http://www.test.com/myclass", ElementName = "Req")]
public partial class request
{
    private requestHead headField;

    private requestBody bodyField;

    public request()
    {
        this.bodyField = new requestBody();
        this.headField = new requestHead();
    }

    [XmlAttribute("schemaLocation", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
    public string xsiSchemaLocation = "http://www.test.com/myclass.xsd";

    [XmlElement("head", Namespace = "")]
    public requestHead head
    {
        get
        {
            return this.headField;
        }
        set
        {
            this.headField = value;
        }
    }

    [XmlElement("body", Namespace = "")]
    public requestBody body
    {
        get
        {
            return this.bodyField;
        }
        set
        {
            this.bodyField = value;
        }
    }
}

public partial class requestHead
{
    private string headAField;

    private string headBField;

    public string hA
    {
        get
        {
            return this.headAField;
        }
        set
        {
            this.headAField = value;
        }
    }

    public string hB
    {
        get
        {
            return this.headBField;
        }
        set
        {
            this.headBField = value;
        }
    }
}

public partial class requestBody
{
    private string R1Field;

    private string R2Field;

    private requestBodyR3 R3Field;

    private requestBodyR4 R4Field;

    public requestBody()
    {
        this.R4Field = new requestBodyR4();
        this.R3Field = new requestBodyR3();
    }

    public string R1
    {
        get
        {
            return this.R1Field;
        }
        set
        {
            this.R1Field = value;
        }
    }

    public bool ShouldSerializeR1() { return !String.IsNullOrEmpty(R1); }

    public string R2
    {
        get
        {
            return this.R2Field;
        }
        set
        {
            this.R2Field = value;
        }
    }

    public bool ShouldSerializeR2() { return !String.IsNullOrEmpty(R2); }

    public requestBodyR3 R3
    {
        get
        {
            return this.R3Field;
        }
        set
        {
            this.R3Field = value;
        }
    }

    public bool ShouldSerializeR3() { return requestBodyR3.ShouldSerializeRequestBodyR3(); }

    public requestBodyR4 R4
    {
        get
        {
            return this.R4Field;
        }
        set
        {
            this.R4Field = value;
        }
    }
}

public partial class requestBodyR3
{

    private string R31Field;

    private string R32Field;

    public static bool ShouldSerializeRequestBodyR3()
    {
        bool blnRetVal = false;

        //Add code to test these values later

        return blnRetVal;
    }

    public string R31
    {
        get
        {
            return this.R31Field;
        }
        set
        {
            this.R31Field = value;
        }
    }

    public string R32
    {
        get
        {
            return this.R32Field;
        }
        set
        {
            this.R32Field = value;
        }
    }
}

public partial class requestBodyR4
{
    private string R41Field;

    public string R41
    {
        get
        {
            return this.R41Field;
        }
        set
        {
            this.R41Field = value;
        }
    }
}

The only problem now is the lack of the line xmlns="http://www.Test.com/MyClass">

If i add the following code to the namespace section:

ns.Add("", "http://www.test.com/Myclass");

I get the output i require but NOTICEi jhad to change the case on one of the letters to get the output if the case is the same as the namespace MyClass then it does not output.

Thanks In Advance

Upvotes: 0

Views: 2839

Answers (1)

Ralf
Ralf

Reputation: 1352

The Namespace is MyClass and the Elementname is Req. So you need to define the Namespace.

XmlSerializerNamespaces ns = new XmlSerializerNamespaces();            
ns.Add("MyClass", "http://www.test.com/myclass");

and call a Serialize overload that takes an XmlSerializerNamespaces instance. The Request class itself is then an Element named Req.

[XmlRoot(Namespace = "http://www.test.com/myclass", ElementName = "Req")]
public class Request
{
    [XmlElement("R1", Namespace = "")]
    public string R1 { get; set; }
    public bool ShouldSerializeR1()  { return !string.IsNullOrWhiteSpace(R1); }

    [XmlAttribute("schemaLocation", Namespace = "")]
    public string xsiSchemaLocation = "http://www.test.com/myclass.xsd";
}

schemaLocation can be added via a Property declared as a Xml Attribute. If a property should be serialize can be controlled by a method with a ShouldSerialize*MyLovelyPropertyName()* syntax.

Upvotes: 1

Related Questions