50

I want XML in the following format:

<configuration><!-- Only one configuration node -->
  <logging>...</logging><!-- Only one logging node -->
  <credentials>...</credentials><!-- One or more credentials nodes -->
  <credentials>...</credentials>
</configuration>

I'm trying to create a class Configuration that has the [Serializable] attribute. To serialize the credentials nodes, I have the following:

[XmlArray("configuration")]
[XmlArrayItem("credentials", typeof(CredentialsSection))]
public List<CredentialsSection> Credentials { get; set; }

However, when I serialize this to XML, the XML is in the following format:

<configuration>
  <logging>...</logging>
  <configuration><!-- Don't want credentials nodes nested in a second
                      configuration node -->
    <credentials>...</credentials>
    <credentials>...</credentials>
  </configuration>
</configuration>

If I remove the [XmlArray("configuration")] line, I get the following:

<configuration>
  <logging>...</logging>
  <Credentials><!-- Don't want credentials nodes nested in Credentials node -->
    <credentials>...</credentials>
    <credentials>...</credentials>
  </Credentials>
</configuration>

How can I serialize this the way I want, with multiple <credentials> nodes within the single root node <configuration>? I wanted to do this without having to implement IXmlSerializable and do custom serialization. This is how my class is described:

[Serializable]
[XmlRoot("configuration")]
public class Configuration : IEquatable<Configuration>

1 Answer 1

81

The following should serialize properly the way you want. The clue being [XmlElement("credentials")] on the list. I did this by taking your xml, generating a schema (xsd) from it in Visual Studio. Then running xsd.exe on the schema to generate a class. (And some small edits)

public class CredentialsSection
{
    public string Username { get; set; }
    public string Password { get; set; }
}

[XmlRoot(Namespace = "", IsNullable = false)]
public class configuration
{
    /// <remarks/>
    public string logging { get; set; }

    /// <remarks/>
    [XmlElement("credentials")]
    public List<CredentialsSection> credentials { get; set; }

    public string Serialize()
    {
        var credentialsSection = new CredentialsSection {Username = "a", Password = "b"};
        this.credentials = new List<CredentialsSection> {credentialsSection, credentialsSection};
        this.logging = "log this";
        XmlSerializer s = new XmlSerializer(this.GetType());
        StringBuilder sb = new StringBuilder();
        TextWriter w = new StringWriter(sb);
        s.Serialize(w, this);
        w.Flush();
        return sb.ToString();
    }
}

give the following output

<?xml version="1.0" encoding="utf-16"?>
<configuration xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <logging>log this</logging>
  <credentials>
    <Username>a</Username>
    <Password>b</Password>
  </credentials>
  <credentials>
    <Username>a</Username>
    <Password>b</Password>
  </credentials>
</configuration>
Sign up to request clarification or add additional context in comments.

6 Comments

Yep, that worked! I was so set on "it's a List, gotta use the XmlArrayItem attribute somewhere" that I didn't even think of making it a regular XmlElement.
good answer, i had the same problem - i wanted to remove: <DATAITEMS> <DATAITEM/> <DATAITEM/> </ DATAITEMS> resolved it with: [XmlElement("DATAITEM")] public List<string> DATAITEM { get; set; }
Thanks Mikael. This helped me out with my problem today. +1
It works only when using XmlSerializer. It doesn't work when used inside a WCF DataContract, in a WCF DataMember, like [XmlElement("credentials")] [DataMember] public List<CredentialsSection> credentials { get; set; }. It seems like WCF ignores the Xml* attributes for serialization. Any suggestion?
thanks a lot ! That was killing me all the XmlArray , XmlArrayItem, ... The answer was so simple easy.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.