Need some help with reading XML and storing values in Dictionary/List

Hi All,

I'm new to C# and new to programming in general and although I'm ok at powershell, I have never worked with XML so this is a bit of a mystery topic for me.

I'm keeping some data about the group, its domain and some user attribute values in a structure shown below, in an XML file that I can read on the Initialise() method of the MA Extensions code.

<Groups>
  
  <Group>
    <GroupName samaccountname="FGPP-USA" Domain="usa.iam.net">
      <AccountType>01</AccountType>
      <AccountType>02</AccountType>
      <AccountType>03</AccountType>
    </GroupName>
  </Group>

  <Group>
    <GroupName samaccountname="FGPP-UK" Domain="uklondon.iam.net">
      <AccountType>04</AccountType>
      <AccountType>05</AccountType>
      <AccountType>06</AccountType>
    </GroupName>
  </Group>

  <Group>
    <GroupName samaccountname="FGPP-ROOT1" Domain="iam.net">
      <AccountType>07</AccountType>
      <AccountType>08</AccountType>
      <AccountType>09</AccountType>
    </GroupName>
  </Group>

  <Group>
    <GroupName samaccountname="FGPP-ROOT2" Domain="iam.net">
      <AccountType>01</AccountType>
      <AccountType>02</AccountType>
      <AccountType>03</AccountType>
      <AccountType>04</AccountType>
    </GroupName>
  </Group>
  
 </Groups>

So I have an single AD Forest consisting of some domains. I have a few groups per domain which I want FIM Sync to update memberships in. Using one management agent I'm reading groups and person into metaverse. I project all users from AD as persons to metaverse. However, when it comes to groups, I want to use the ShouldProjectToMV method in the import flow code to only project if a group has a samaccountname value and domain value matching with something in the XML (eg. <GroupName samaccountname="FGPP-ROOT2" Domain="iam.net">)

The next thing I want to do is get a list of AccountType values as a list that I can foreach with and find the person objects in metaverse and write to a custom mv attribute called memberSTR [multivalue string]. However, where I need help is some LINQ XML type. I would ideally want a function I can call from within MapAttributesForImport() which uses LINQ XML and returns me a list of AccountTypes for a specific Group for a specific domain.

I will have about 100 such groups so even though this would take a performance hit as FIM will have to calculate memberships for every group, its still OK.

So my question is

1. How do I get a list of all groups with samaccountname and domains from that XML?

2. If I know the samaccountname and domain of a group, how can I get the respective AccountType values from that XML?

I posted this question somewhere else and the gentleman was very helpful but they proposed a solution which is not suitable. I know the management will give me some more groups in future for FIM to update memberships. So there will be more additions to XML, however, I don't think the structure will change much.

Please help!

March 31st, 2015 5:00am

Why isn't solution suitable?  I don't think you understood the code I posted.  There were three sections

1) Test data

2) Code that wrote any XML data in the format you provided.

3) Code that would read any XML data in the format you provided.

I think you didn't understand that I only put the test data into the code to get the rest of the code working.  Going the LINQ XML approach is much more complicated than the solution I provided.

Free Windows Admin Tool Kit Click here and download it now
March 31st, 2015 5:48pm

Hi JDweng,

Thanks for your response.

Honestly, I did not understand the code you provided. I also couldn't figure out how to put this is the MA or MV extensions files to compile the DLLs.

All I really wanted was a simple way to retrieve the simple array of AccountTypes. I looked at LINQ XML samples but I couldn't get it to work either.

In the end, I decided to store the data in a SQL table instead of XML as I know how to read that using C#.

Regards,

GT

March 31st, 2015 6:42pm

You could easily of put my code into a class like the code below.  Ask if you don't know.  Your question about "static" wasn't very clear.  You should of either said that you needed the code into a separate class or you were building a DLL.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.IO;
namespace ConsoleApplication1
{
    class Program
    {
        
        static void Main(string[] args)
        {
            CXML cXML = new CXML();
            cXML.WriteXML(cXML.testData);
            CXML.Groups groups = cXML.ReadXML();

            string samaccountname = "FGPP-ROOT";
            string domain = "iam.net";

            string[] AccountTypes = cXML.GetAccountTypes(samaccountname, domain);

        }
    }

    public class CXML
    {
        const string FILENAME = @"c:\temp\Test.xml";
        Dictionary<string, GroupName> dict = null;

        public Groups testData = new Groups()
        {
            group = new List<Group>(){
                new Group(){ 
                    groupName = new GroupName(){
                        samaccountname = "FGPP-USA",
                        domain = "usa.iam.net",
                        accountType = new List<string>() {"01","02","03"}
                    }
                },
                new Group(){ 
                    groupName = new GroupName(){
                        samaccountname = "FGPP-UK",
                        domain = "uklondon.iam.net",
                        accountType = new List<string>() {"04","05","06"}
                    }
                },
                new Group(){ 
                    groupName = new GroupName(){
                        samaccountname = "FGPP-ROOT",
                        domain = "iam.net",
                        accountType = new List<string>() {"07","08","09"}
                    }
                }
            }
        };

        public void WriteXML(Groups groups)
        {

            XmlSerializer serializer = new XmlSerializer(typeof(Groups));

            StreamWriter writer = new StreamWriter(FILENAME);
            XmlSerializerNamespaces _ns = new XmlSerializerNamespaces();
            _ns.Add("", "");
            serializer.Serialize(writer, groups, _ns);
            writer.Flush();
            writer.Close();
            writer.Dispose();
        }
        
        public Groups ReadXML()
        {

            XmlSerializer xs = new XmlSerializer(typeof(Groups));
            XmlTextReader reader = new XmlTextReader(FILENAME);
            Groups newGroups = (Groups)xs.Deserialize(reader);

            dict = newGroups.group.AsEnumerable()
                .GroupBy(x => x.groupName.samaccountname, y => y.groupName)
                .ToDictionary(x => x.Key, y => y.FirstOrDefault());

            return newGroups;
        }

        
        public string[] GetAccountTypes(string samaccountname, string domain)
        {
            return dict[samaccountname].accountType.ToArray();
        }

        [XmlRoot("Groups")]
        public class Groups
        {
            [XmlElement("Group")]
            public List<Group> group { get; set; }
        }

        [Serializable, XmlRoot("Group")]
        public class Group
        {
            [XmlElement("GroupName")]
            public GroupName groupName { get; set; }
        }
        [Serializable, XmlRoot("GroupName")]
        public class GroupName
        {
            [XmlAttribute("samaccountname")]
            public string samaccountname { get; set; }
            [XmlAttribute("Domain")]
            public string domain { get; set; }
            [XmlElement("AccountType")]
            public List<string> accountType { get; set; }
        }
    }


}

Free Windows Admin Tool Kit Click here and download it now
March 31st, 2015 11:03pm

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics