8

I have defined type as Example as shown below, after instantiating a object and serializing using XmlSerializer, i am getting x003A instead of colon :

Here's my code:

 public class Example
        {
            [XmlElement("Node1")]
            public string Node1 { get; set; }
            [XmlElement("rd:Node2")]
            public string Node2 { get; set; }
        }

Serialization code

 Example example = new Example { Node1 = "value1", Node2 = "value2" };

            XmlSerializerNamespaces namespaceSerializer = new XmlSerializerNamespaces(); 
            namespaceSerializer.Add("rd", @"http://schemas.microsoft.com/SQLServer/reporting/reportdesigner");
            System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(Example));
            string path = System.Windows.Forms.Application.StartupPath + "//example.xml";
            using (StreamWriter writer = new StreamWriter(path))
            {
                serializer.Serialize(writer, example, namespaceSerializer);
            }

Expected Result

<?xml version="1.0" encoding="utf-8"?>
<Example xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Node1>value1</Node1>
  <rd:Node2>value2</rd:Node2>
</Example>

Actual Result:

<?xml version="1.0" encoding="utf-8"?>
<Example xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Node1>value1</Node1>
  <rd_x003A_Node2>value2</rd_x003A_Node2>
</Example>

Any help and direction in this are greatly appreciated. Thanks in advance!

2 Answers2

9

You have to do it like this:

public class Example {
    [XmlElement("Node1")]
    public string Node1 { get; set; }
    // define namespace like this, not with a prefix
    [XmlElement("Node2", Namespace = "http://schemas.microsoft.com/SQLServer/reporting/reportdesigner")]
    public string Node2 { get; set; }
}

Then when serializing:

var serializer = new XmlSerializer(typeof(Example));
var ns = new XmlSerializerNamespaces();
// map prefix to namespace like this
ns.Add("rd", "http://schemas.microsoft.com/SQLServer/reporting/reportdesigner");
var ms = new MemoryStream();      
// use namespaces while serializing
serializer.Serialize(ms, new Example {
    Node1 = "node1",
    Node2 = "node2"
}, ns);
Evk
  • 98,527
  • 8
  • 141
  • 191
  • i have done the same thing but no use , as mentioned in comments i have defined namespace for the rd , let me edit the post and add Serailization part for more info which i tried – ANR Upgraded Version Dec 10 '17 at 10:38
  • I tested this before posting and it produces expected result (well, not exactly, because your expected result is invalid xml, and this produces valid one). Note that I changed attributes on your Node2 property. – Evk Dec 10 '17 at 10:40
  • Well i didnt notice that change you made XmlElement("rd:Node2") to XmlElement("Node2") , this is working fine now thank you , i appreciate your help – ANR Upgraded Version Dec 10 '17 at 10:53
  • Does the namespace have to be valid? Reason I ask is that I wanted different prefixes on different nodes, and I'm not sure what namespace they'd come from? – Max Power Nov 15 '18 at 10:50
  • @MaxPower in what sense "valid"? – Evk Nov 15 '18 at 11:08
  • @Evk, Does the URL entered in the namespace need to resolve to anything? Apologies, I don't know too much about namespaces! – Max Power Nov 16 '18 at 19:32
  • 1
    @MaxPower in short - they are treated as unique identifiers (so, just as character string) and not need to resolve to anything. Some XML parsers even won't mind if namespace is not URL at all. Why specification is using URL as such identifier is complicated subject and many people think it was a bad idea (I think so too), but there is a specification so we better follow it. Note that because of the above - two URLs which resolve to the same document will still represent different namespaces if they are different (even if only in case) – Evk Nov 16 '18 at 19:45
0

Try to avoid the attribute-based approach for such task.

[XmlElement("rd:Node2")] //this will create rd_x003A_Node2

I would suggest using serialization functionality. Take a look at https://learn.microsoft.com/en-us/dotnet/api/system.xml.serialization.xmlserializernamespaces?view=net-5.0

Viktor
  • 380
  • 5
  • 14