1

My confusion is, I am using .Net C# XMLSerializer to serialize a customize defined type, using the schema/cs file generated by XSD tool from an input original XML file. But the generated serialized XML file namespace is different from original XML input file. Especially from original XML file, Envelope belongs to namespace soapenv, but in the serialized XML file, Envelope belongs to default namespace. Any ideas what is wrong?

Here is how I use XSD tool to generate schema file and cs file for the customized defined type from XML input file XMLFile1.xml,

BTW: XML files can be downloaded from,

http://www.mediafire.com/?nwngwzz3gmm

D:\>xsd XMLFile1.xml
Microsoft (R) Xml Schemas/DataTypes support utility
[Microsoft (R) .NET Framework, Version 2.0.50727.3038]
Copyright (C) Microsoft Corporation. All rights reserved.
Writing file 'D:\XMLFile1.xsd'.

D:\>xsd XMLFile1.xsd XMLFile1_app1.xsd /classes
Microsoft (R) Xml Schemas/DataTypes support utility
[Microsoft (R) .NET Framework, Version 2.0.50727.3038]
Copyright (C) Microsoft Corporation. All rights reserved.
Writing file 'D:\XMLFile1_XMLFile1_app1.cs'.

Here is how I use C# code to serialize the file and output to TestOutputFile.xml,

static void Main(string[] args)
{
    Envelope en = new Envelope();
    en.Items = new EnvelopeBody[1];
    en.Items[0] = new EnvelopeBody();
    en.Items[0].QueryResponse = new QueryResponseFaculties[1];
    en.Items[0].QueryResponse[0] = new QueryResponseFaculties();
    en.Items[0].QueryResponse[0].Name = "John";

    XmlSerializer serializer =
     new XmlSerializer(typeof(Envelope));
    TextWriter writer = new StreamWriter("TestOutputFile.xml");

    serializer.Serialize(writer, en);
    writer.Close();

    return;
}

The original XML file is,

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <QueryResponse xmlns="http://schemas.mycorp.com/test">
      <Faculties>
        <Name>
          John
        </Name>
      </Faculties>
    </QueryResponse>
  </soapenv:Body>
</soapenv:Envelope>

The serialized XML file is,

<?xml version="1.0" encoding="utf-8"?>
<Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns="http://schemas.xmlsoap.org/soap/envelope/">
  <Body>
    <QueryResponse xmlns="http://schemas.mycorp.com/test">
      <Faculties>
        <Name>John</Name>
      </Faculties>
    </QueryResponse>
  </Body>
</Envelope>

EDIT 1:

Current code is,

static void Main(string[] args)
{
    XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
    ns.Add("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
    ns.Add("", "http://schemas.mycorp.com/test");
    ns.Add("xsd", "http://www.w3.org/2001/XMLSchema");
    ns.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");

    Envelope en = new Envelope();
    en.Items = new EnvelopeBody[1];
    en.Items[0] = new EnvelopeBody();
    en.Items[0].QueryResponse = new QueryResponseFaculties[1];
    en.Items[0].QueryResponse[0] = new QueryResponseFaculties();
    en.Items[0].QueryResponse[0].Name = "John";

    XmlSerializer serializer =
     new XmlSerializer(typeof(Envelope));
    TextWriter writer = new StreamWriter("TestOutputFile.xml");

    serializer.Serialize(writer, en, ns);
    writer.Close();

    return;
}

Current output (serialized XML file) is,

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://schemas.mycorp.com/test"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <QueryResponse>
      <Faculties>
        <Name>John</Name>
      </Faculties>
    </QueryResponse>
  </soapenv:Body>
</soapenv:Envelope>

I want the output to be (notice the location of string xmlns="http://schemas.mycorp.com/test"),

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <QueryResponse xmlns="http://schemas.mycorp.com/test">
      <Faculties>
        <Name>John</Name>
      </Faculties>
    </QueryResponse>
  </soapenv:Body>
</soapenv:Envelope>

thanks in advance, George

3
  • updated my example to show it working with full code Commented Jul 8, 2009 at 10:31
  • You keep saying the namespace is in the wrong location, but when I run the code I posted the outpuot is exactly as you requested. I wonder if this is a framework version thing; I'm in 3.5SP1 Commented Jul 9, 2009 at 6:58
  • George, part of your problem is that you're serializing the envelope as well as the contents. Why are you doing that? Are you not calling a web service? Commented Jul 9, 2009 at 7:07

2 Answers 2

3

You need to use the XmlSerializerNamespaces class to set up your namespaces, then when serializing you need to pass that instance of XmlSerializerNamespces in along with your object. You will also need to set the namespace of your classes and/or properties using the XmlRoot and XmlElement attributes:

static void Main(string[] args)
{
    Envelope en = new Envelope();
    en.Items = new EnvelopeBody[1];
    en.Items[0] = new EnvelopeBody();
    en.Items[0].QueryResponse = new QueryResponseFaculties[1];
    en.Items[0].QueryResponse[0] = new QueryResponseFaculties();
    en.Items[0].QueryResponse[0].Name = "John";

    XmlSerializer serializer =
     new XmlSerializer(typeof(Envelope));
    TextWriter writer = new StreamWriter("TestOutputFile.xml");

    XmlSerlializerNamespaces xsn = new XmlSerializerNamespaces();
    xsn.Add("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");

    serializer.Serialize(writer, en, xsn);
    writer.Close();

    return;
}

[XmlRoot(Namespace="http://schemas.xmlsoap.org/soap/envelope/")]
class Envelope
{
    // ...
}
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks jrista, I have tried your solution, only one minor issue left, which is I want to define default namespace xmlns="schemas.mycorp.com/test from element QueryResponse, and not from the top level element Envelope, any solutions?
Your solution will define all namespace at top level XML element of the serialized output XML file.
Just use the XmlElement attribute to set the namespace for any property individually.
Sorry jrista, I think I did not make myself understood or I misunderstand your points. I think your solution did not solve my issue. Please refers to EDIT 1 section of my original post, which contains the current result of serialized file and my expected output serialized file. Any solutions?
3

Aren't they interchangeable? In one it is using xmlns to set the namespace at the element, and in the other a xmlns:soapenv alias - but the meaning is the same, and IMO the second version is cleaner.

There is the XmlSerializerNamespaces class that can fix this ; full example:

using System;
using System.Xml.Serialization;
[XmlRoot(Namespace="http://schemas.xmlsoap.org/soap/envelope/")]
public class Envelope {
    public Body Body { get; set; }
}
public class Body {
    [XmlElement(Namespace="http://schemas.mycorp.com/test")]
    public QueryResponse QueryResponse { get; set; }
}
public class QueryResponse {
    public Faculties Faculties { get; set; }
}
public class Faculties {
    public string Name { get; set; }
}
static class Program {
    static void Main() {
        XmlSerializer ser = new XmlSerializer(typeof(Envelope));
        XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
        ns.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");
        ns.Add("xsd", "http://www.w3.org/2001/XMLSchema");
        ns.Add("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
        Envelope env = new Envelope {
            Body = new Body {
                QueryResponse = new QueryResponse {
                     Faculties = new Faculties { Name = "John"}
                }
            }
        };
        ser.Serialize(Console.Out, env, ns);
    }
}

Output (@encoding is because of Console.Out):

<?xml version="1.0" encoding="ibm850"?>
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:xsd="http://www.w3.org/2001/XMLSchema"
      xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <QueryResponse xmlns="http://schemas.mycorp.com/test">
      <Faculties>
        <Name>John</Name>
      </Faculties>
    </QueryResponse>
  </soapenv:Body>
</soapenv:Envelope>

9 Comments

Hi Marc, I agree from XML syntax, they are the same. But for the limitation of my legacy program, I have to put Envelope into namespace soapenv. Any ideas how to resolve this issue?
Thanks Marc, I have tried your solution, only one minor issue left, which is I want to define default namespace xmlns="schemas.mycorp.com/test from element QueryResponse, and not from the top level element Envelope, any solutions?
Just add [XmlElement(Namespace="schemas.mycorp.com/test")] on the property you want to be in a different (default) namespace.
@George2: you should file a bug report against the legacy system, reminding them that they should support XML. What they currently support looks something like XML, but does not support basic standards.
We've already said... use XmlSerializerNamespaces and mark the property... I can try to do an example, but...
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.