Michael Robinson
Michael Robinson

Reputation: 1142

C# - xml from vendor has multiple element names for the same object. How to serialize them into the same object?

I have this xml from our vendor (an excerpt):

<Roles xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:immutable="http://www.digitalmeasures.com/schema/immutable">
    <immutable:Role roleKey="INDIVIDUAL-ACTIVITIES-University-DataBackupService" text="Data Backup Service">
        <Item xlink:type="simple" xlink:href="/login/service/v4/Role/INDIVIDUAL-ACTIVITIES-University-DataBackupService"/>
        <Users xlink:type="simple" xlink:href="/login/service/v4/RoleUser/INDIVIDUAL-ACTIVITIES-University-DataBackupService"/>
    </immutable:Role>
    <Role roleKey="INDIVIDUAL-ACTIVITIES-University-DepartmentUpdatePrimaryAssignmentOrg" text="Department: Update Primary Assignment Org">
        <Item xlink:type="simple" xlink:href="/login/service/v4/Role/INDIVIDUAL-ACTIVITIES-University-DepartmentUpdatePrimaryAssignmentOrg"/>
        <Users xlink:type="simple" xlink:href="/login/service/v4/RoleUser/INDIVIDUAL-ACTIVITIES-University-DepartmentUpdatePrimaryAssignmentOrg"/>
    </Role>
</Roles>

I have these classes set up in my c# code:

public class Role
{
    [XmlAttribute]
    public string roleKey { get; set; }
    [XmlAttribute]
    public string text { get; set; }
    [XmlAttribute]
    public string Item { get; set; }
    [XmlAttribute]
    public string Users { get; set; }
}

//Class to hold our array of <DailyStat>
[Serializable]
[XmlRootAttribute("Roles")]
//[XmlRootAttribute("immutable:Roles")]
public class Roles
{
    [XmlElement("Role")]
    public Role[] thisRole { get; set; }
}

The xml I get from the vendor (via a web service), has 20 elements tagged Role and 6 tagged as immutable:Role. When I run my code, I only see the 20 Role items, but I want all 26 items. How can I go about getting them?

Upvotes: 0

Views: 174

Answers (2)

Michael Robinson
Michael Robinson

Reputation: 1142

Just posting this out there for other folks, I found this website that will convert xml to c# objects. I like the results better than what Paste Special -> Paste XML as Classes was giving me. XML to c# website

Upvotes: 0

andrei.ciprian
andrei.ciprian

Reputation: 3025

My weapon of choice for class generation is xsd, I find it much easier controlling attributes like that, rather than producing them on my own, especially in tricky scenarios like yours. Basically, it's a tale of two namespaces. Identical structure, different attribute decorations. There's 2 different namespaces no and imm to separate the Role classes. Item and Users nodes have the CT common type, and no.Role and imm.Role share this type.

internal static class ct
{
 public const string nsImmutable = "http://www.digitalmeasures.com/schema/immutable";
 public const string nsXLink = "http://www.w3.org/1999/xlink";
}

[Serializable]
[XmlType(AnonymousType = true)]
[XmlRoot(Namespace = "", IsNullable = false)]
public partial class Roles
{
  [XmlElement("Role", typeof(no.Role))]
  [XmlElement("Role", typeof(imm.Role), Namespace = ct.nsImmutable)]
  public object[] Items { get; set; }
}

public partial class BaseRole
{
  [XmlAttribute("roleKey")]
  public string RoleKey { get; set; }

  [XmlAttribute("text")]
  public string Text { get; set; }
}

  [Serializable]
  [XmlType(AnonymousType = true)]
  //[XmlRoot(Namespace = "", IsNullable = false)]
  public partial class CT
  {
    [XmlAttribute(Form = XmlSchemaForm.Qualified, Namespace = ct.nsXLink, AttributeName = "type")]
    public string Type { get; set; }

    [XmlAttribute(Form = XmlSchemaForm.Qualified, Namespace = ct.nsXLink, AttributeName = "href")]
    public string Href { get; set; }
  }

namespace imm
{
  [Serializable]
  [XmlType(AnonymousType = true, Namespace = ct.nsImmutable)]
  [XmlRoot(Namespace = ct.nsImmutable, IsNullable = false)]
  public partial class Role : BaseRole
  {
    [XmlElement(Namespace = "", Type = typeof(CT), ElementName = "Item")]
    public CT Item { get; set; }

    [XmlElement(Namespace = "", Type = typeof(CT), ElementName = "Users")]
    public CT Users { get; set; }
  }      
}


namespace no
{
  [Serializable]
  [XmlType(AnonymousType = true)]
  public partial class Role : BaseRole
  {
    [XmlElement("Item", typeof(CT))]
    public CT Item { get; set; }

    [XmlElement("Users", typeof(CT))]
    public CT Users { get; set; }
  }
}

Upvotes: 1

Related Questions