1

I have a situation where I need to generate the below XML dynamically in my C# code. For example, the XML text would be

<Envelope>
  <Body>
    <Login>
      <USERNAME>username</USERNAME>
      <PASSWORD>Sm@rt123</PASSWORD>
    </Login>
  </Body>
</Envelope>

The requirement is to send the above XML format as a string to an API call, which would get some responses as a string in the XML format.

My question is the above example is for a Login Api call, for all the api calls, the elements Envelope and Body are same and based on the api call, the other parts change like for Login api, I need to mention a xml element as Login with its attributes username and password.

Till now I have been hardcoding the above string and trying to test if the functionality is working fine, but now I need to automate this process of generating these tags for respective different api calls. I need to know how can this be done and what is the best approach for the same.

SwDevMan81
  • 48,814
  • 22
  • 151
  • 184
Vidya
  • 126
  • 2
  • 4
  • 16
  • Hello steve, please have a look now... I was editing the question. – Vidya May 22 '12 at 15:52
  • Hello banging I have tried the option suggested below by SteveDog, but I am getting stuck so wanted to have various approaches and what would be the best way to handle it – Vidya May 22 '12 at 16:17

4 Answers4

4

Something fluent like this...

internal class Program
{
    private static void Main(string[] args)
    {
        new API()
            .Begin()
            .Login("username", "password")
            .Send("someuri");
        Console.ReadLine();
    }
}

public class API
{
    public static readonly XNamespace XMLNS = "urn:hello:world";
    public static readonly XName XN_ENVELOPE = XMLNS + "Envelope";
    public static readonly XName XN_BODY = XMLNS + "Body";

    public XDocument Begin()
    {
        // this just creates the wrapper
        return new XDocument(new XDeclaration("1.0", Encoding.UTF8.EncodingName, "yes")
                                , new XElement(XN_ENVELOPE
                                    , new XElement(XN_BODY)));
    }
}

public static class APIExtensions
{
    public static void Send(this XDocument request, string uri)
    {
        if (request.Root.Name != API.XN_ENVELOPE)
            throw new Exception("This is not a request");

        // do something here like write to an http stream or something
        var xml = request.ToString();
        Console.WriteLine(xml);
    }
}

public static class APILoginExtensions
{
    public static readonly XName XN_LOGIN = API.XMLNS + "Login";
    public static readonly XName XN_USERNAME = API.XMLNS + "USERNAME";
    public static readonly XName XN_PASSWORD = API.XMLNS + "PASSWORD";

    public static XDocument Login(this XDocument request, string username, string password)
    {
        if (request.Root.Name != API.XN_ENVELOPE)
            throw new Exception("This is not a request");

        // you can have some fancy logic here
        var un = new XElement(XN_USERNAME, username);
        var pw = new XElement(XN_PASSWORD, password);
        var li = new XElement(XN_LOGIN, un, pw);
        request.Root.Element(API.XN_BODY).Add(li);
        return request;
    }
}
Juan Ayala
  • 3,388
  • 2
  • 19
  • 24
  • Hi Juan, thanks for the swift reply, I will try the below option suggested by Steve as I was trying that before... – Vidya May 22 '12 at 16:20
  • No problem :-) I expanded my example to use namespaces. I was curious to try it :-) – Juan Ayala May 22 '12 at 16:49
2
/// <summary>
///   Create an xml string in the expected format for the login API call.
/// </summary>
/// <param name="user">The user name to login with.</param>
/// <param name="password">The password to login with.</param>
/// <returns>
///   Returns the string of an xml document with the expected schema, 
///   to use with the login API.
/// </returns>
private static string GenerateXmlForLogin(string user, string password)
{
    return
        new XElement("Envelope",
            new XElement("Body",
                new XElement("Login",
                    new XElement("USERNAME", user),
                    new XElement("PASSWORD", password)))).ToString();
}
Seth Flowers
  • 8,990
  • 2
  • 29
  • 42
  • This has a problem when the user name or password contain characters not allowed in XML elements. It'd be best to use XML serialization using an existing library, such as a `DataContractSerializer`. The XML looks suspiciously like a SOAP message with some parts removed, so you might be able to do this very easily by using a WSDL that describes the service, adding it to your project as a Service Reference. – Tim S. May 22 '12 at 16:03
  • @TimS. Good point - I updated the answer to use XElements, which should alleviate this concern for the majority of cases. – Seth Flowers May 22 '12 at 16:20
  • Hello Tim, I am very new to this XML with C# ... I am writing a windows service to handle all this as the scope of this task is very narrow. I hope you are talking about WCF .. I am not sure just a wild guess ... – Vidya May 22 '12 at 16:22
1

If you write the c# code in wpf ,this code will help you well to dynamically generate xml file.

using System.Xml;


public Window1()
    {
        this.InitializeComponent();

        XmlDocument myxml = new XmlDocument();

        XmlElement envelope_tag = myxml.CreateElement("Envelope");

        XmlElement body_tag = myxml.CreateElement("Body");
        envelope_tag.AppendChild(body_tag);

        XmlElement Login_tag=myxml.CreateElement("Login");
        body_tag.AppendChild(Login_tag);

        XmlElement username = myxml.CreateElement("USERNAME");
        username.InnerText = "username";
        Login_tag.AppendChild(username);

        XmlElement password = myxml.CreateElement("PASSWORD");
        password.InnerText = "rt123";
        Login_tag.AppendChild(password);

        myxml.AppendChild(envelope_tag);
        myxml.Save(@"D:\Myxml.xml");   //you can save this file wherever you want to store. it may c: or D: and etc...      

    }

The output will be like this

MyXml

CHANDRA
  • 4,778
  • 8
  • 32
  • 51
0

I was going to suggest serialization as a simple way to output to XML. Here's a simple example:

First create the classes

Public Class Login
    Public Property USERNAME() As String
        Get
            Return _USERNAME
        End Get
        Set(ByVal value As String)
            _USERNAME = value
        End Set
    End Property
    Private _USERNAME As String


    Public Property PASSWORD() As String
        Get
            Return _PASSWORD
        End Get
        Set(ByVal value As String)
            _PASSWORD = value
        End Set
    End Property
    Private _PASSWORD As String
End Class


Public Class Body
    Public Property Login() As Login
        Get
            Return _login
        End Get
        Set(ByVal value As LoginClass)
            _login = value
        End Set
    End Property
    Private _login As Login = New Login()
End Class


Public Class Envelope
    Public Property Body() As Body
        Get
            Return _body
        End Get
        Set(ByVal value As Body)
            _body = value
        End Set
    End Property
    Private _body As Body = New Body()
End Class

Then, create an envelope object, populate it, and then serialize it:

Dim envelope As New Envelope()
envelope.Body.Login.USERNAME = "username"
envelope.Body.Login.PASSWORD = "Sm@rt123"

Dim stream As MemoryStream = New MemoryStream()
Dim textWriter As XmlTextWriter = New XmlTextWriter(stream, New System.Text.UTF8Encoding(False))
Dim serializer As XmlSerializer = New XmlSerializer(GetType(Envelope))
Dim namespaces As XmlSerializerNamespaces = New XmlSerializerNamespaces()
namespaces.Add("", "")
serializer.Serialize(textWriter, envelope, namespaces)
Dim doc As XmlDocument = New XmlDocument()
doc.LoadXml(Encoding.UTF8.GetString(stream.ToArray()))
Dim xmlText As String = doc.SelectSingleNode("Envelope").OuterXml
Steven Doggart
  • 43,358
  • 8
  • 68
  • 105
  • Hello Steve , will try doing the above changes, I have got some kind of picture now .. will let you know if it worked .. Thanks for the reply. – Vidya May 22 '12 at 16:19
  • Hello Steve , thats a great suggestion thanks a lot it worked .... had to make some small changes , I had one small doubt, what should do to remove the utfcoding in the below expected text .. I just need that should be fine – Vidya May 22 '12 at 16:55
  • Yes, the other options people suggested are all excellent ideas, but often serialization is the most readable in the code. It's very easy to see the XML structure in the code and to make modifications to it. However, if you don't need the full xml document, and you just need the inner XML for the root element, someone else's suggestion may be better. The only way to do that with serialization would be to then load it into an XmlDocument object, select the root element, and get it's XML text. – Steven Doggart May 22 '12 at 17:01