CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6
  1. #1
    Join Date
    Jan 2013
    Posts
    3

    Angry Reading Multi level XML file while using C#

    What would be the easiest way to manipulate the data being mindful that i am really working with an XML file that I have imported into memory:

    <Data>
    <Drives>
    <label>Area 51</label>
    <date>12/10/2012</date>
    <Description>testing site</Description>
    <Status>valid</Status>
    <Membership>
    Username="Jsmith"
    Bool="or"
    username="MGordon"
    </Membership>
    </Drives>

    <Drives>
    <label>Apollo</label>
    <date>12/04/2010</date>
    <Description>fly to the Moon</Description>
    <Status>Terminated</Status>
    <Membership>
    Username="DKerr"
    bool="and"
    Username="Sremi"
    bool="or"
    Group="ApolloReadOnly"
    </Membership>
    </Drives>


    <Drives>
    <label>Deep Impact</label>
    <date>12/06/08</date>
    <Description>Exploring Comet Temple</Description>
    <Status>Achieved</Status>
    <Membership>
    <collection>
    Username="Gblaine"
    Group="SSnype"
    group="Wesson"
    bool="or"
    Computer="Exec-02"
    </Collection>
    </Membership>
    </Drives>
    <Data>


    Ideally, I would need this:

    LabeL Date Description Status Membership

    Area 51 12/10/2012 Testing Site valid Jsmtih or MGordon

    Apollo 12/04/2010 fly to the Moon Terminated DKerr and Sremi or AppollyReadonly

    Deep impact 12/06/12 Exploring.. Achived this collection is true (GBlaine or SSnype or WEsson or computer=EXec-02)



    Please keep in mind that I am beginnger at this stage.

    Thanks.

  2. #2
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Reading Multi level XML file while using C#

    You can easily read this data with xml serialization. I can show you how to do it with a couple of simple classes using xml attributes.

    But first, I need to ask if you have the ability to alter the xml schema. Your existing xml snippet has some inconsistencies. Can you modifiy that or is it fixed?

  3. #3
    Join Date
    Jan 2013
    Posts
    3

    Re: Reading Multi level XML file while using C#

    Quote Originally Posted by Arjay View Post
    You can easily read this data with xml serialization. I can show you how to do it with a couple of simple classes using xml attributes.

    But first, I need to ask if you have the ability to alter the xml schema. Your existing xml snippet has some inconsistencies. Can you modify that or is it fixed?

    What are the inconsistencies? If you're talking about the data between the membership tags then this is exactly the challenge with this problem.

  4. #4
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Reading Multi level XML file while using C#

    Quote Originally Posted by grego1533 View Post
    What are the inconsistencies? If you're talking about the data between the membership tags then this is exactly the challenge with this problem.
    Well you've got different casing within the tags. Usually xml tags are pascal case (start with a capital letter) or camel case (start with a lower case letter). You can certainly have a mix but it's a bit odd.

    As far as 'collection' element inside the 'Membership' element... that's okay, but the opening tag must exactly match the closing tag. You have <collection>...</Collection> and that isn't valid xml.

  5. #5
    Join Date
    Jan 2013
    Posts
    3

    Re: Reading Multi level XML file while using C#

    Quote Originally Posted by Arjay View Post
    Well you've got different casing within the tags. Usually xml tags are pascal case (start with a capital letter) or camel case (start with a lower case letter). You can certainly have a mix but it's a bit odd.

    As far as 'collection' element inside the 'Membership' element... that's okay, but the opening tag must exactly match the closing tag. You have <collection>...</Collection> and that isn't valid xml.
    You're correct, I have made up the example but the actual data does follow the same concept that you outlined above. I originally shredded the XML in SQL but the unpredictability of the membership tag is painful to manipulate. Thanks for everything!

  6. #6
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Reading Multi level XML file while using C#

    Okay. You can do this with 4 classes and some XmlAttributes on the class properties.

    First the xml.. I fixed up the xml to make it consistent and valid xml.
    Code:
    <?xml version="1.0" encoding="utf-8" ?>
    <data>
      <drive>
        <label>Area 51</label>
        <date>12/10/2012</date>
        <description>testing site</description>
        <status>Valid</status>
        <membership>
          Username="Jsmith"
          Bool="or"
          username="MGordon"
        </membership>
      </drive>
      <drive>
        <label>Apollo</label>
        <date>12/04/2010</date>
        <description>fly to the Moon</description>
        <status>Terminated</status>
        <membership>
          Username="DKerr"
          bool="and"
          Username="Sremi"
          bool="or"
          Group="ApolloReadOnly"
        </membership>
      </drive>
      <drive>
        <label>Deep Impact</label>
        <date>12/06/08</date>
        <description>Exploring Comet Temple</description>
        <status>Achieved</status>
        <membership>
          <collection>
            Username="Gblaine"
            Group="SSnype"
            group="Wesson"
            bool="or"
            Computer="Exec-02"
          </collection>
        </membership>
      </drive>
    </data>
    Next the serialization classes. The Data class is the 'root' class that contains a static Load method. This loads the xml file into a reader, then deserializes it into the Data (and other) class instances.

    Code:
    using System;
    using System.Collections.Generic;
    using System.Xml;
    using System.Xml.Serialization;
    
    namespace CG.MultiLevelXml.Serialization
    {
        public enum Status
        {
            Achieved = 0,
            Terminated = 1,
            Valid = 2
        }
    
        [XmlType(AnonymousType = true)]
        [XmlRoot(ElementName = "data", Namespace = "", IsNullable = false)]
        public class Data
        {
            public static Data Load(string xmlFile)
            {
                var serializer = new XmlSerializer(typeof (Data));
    
                using( var reader = XmlReader.Create(xmlFile))
                {
                    
                    
                    
                    return (Data) serializer.Deserialize(reader);
                }
            }
    
            /// <summary>
            /// Drive list
            /// </summary>
            /// <remarks>
            /// No te: Use a generic collection here to 'back' the drive array.
            /// That way client code won't have to check for Drives == null
            /// </remarks>
            [XmlElement( "drive" )]
            public Drive[] Drives
            {
                get 
                {
                    if( _driveList == null )
                    {
                        _driveList = new List<Drive>();
                    }
                    return _driveList.ToArray();
                }
    
                set
                {
                    if ( _driveList == null )
                    {
                        _driveList = new List<Drive>( );
                    }
    
                    if(value != null)
                    {
                        _driveList.AddRange(value);
                    }
                }
            }
    
            private List<Drive> _driveList = new List<Drive>();
        }
    
        public class Drive
        {
            [XmlElement("label")]
            public string Label { get; set; }
    
            [XmlElement( "date" )]
            public string Date { get; set; }
            
            [XmlElement("description")]
            public string Description { get; set; }
    
            [XmlElement( "status" )]
            public Status Status { get; set; }
    
            [XmlElement( "membership" )]
            public Membership Membership { get; set; }
    
            /// <summary>
            /// Use this property to retrieve the MemberShip or Collection value 
            /// </summary>
            [XmlIgnore]
            public string MembershipValue
            {
                get
                {
                    return IsCollection ? Membership.Collection.Value : Membership.Value;
                }
            }
    
            /// <summary>
            /// Use this property to determine if Membership or Collection
            /// </summary>
            [XmlIgnore]
            public bool IsCollection
            {
                get
                {
                    return (Membership != null && Membership.Collection != null);
                }
            }
    
            /// <summary>
            /// Override to format an output string
            /// </summary>
            /// <returns></returns>
            public override string ToString( )
            {
                return String.Format("{0,-15}{1,-15}{2,-30}{3,-12}{4,-14}{5}", Label, Date, Description, Status, IsCollection, MembershipValue);
            }
        }
    
        public class Membership
        {
            [XmlText]
            public string Value { get; set; }
    
            [XmlElement( "collection", IsNullable = true)]
            public Collection Collection { get; set; }
        }
    
        public class Collection
        {
            [XmlText]
            public string Value { get; set; }
        }
    }
    Finally, using the class...
    Code:
    using System;
    using CG.MultiLevelXml.Serialization;
    
    namespace CG.MultiLevelXml
    {
        class Program
        {
            static void Main( string [ ] args )
            {
                var data = Data.Load("data.xml");
    
                Console.WriteLine( "{0,-15}{1,-15}{2,-30}{3,-12}{4,-14}{5}\n", "Label", "Date", "Description", "Status", "IsCollection", "MembershipValue" );
    
                foreach(var drive in data.Drives)
                {
                    Console.WriteLine(drive);
                }
            }
        }
    }
    Output:
    Code:
    Label          Date           Description                   Status      IsCollection  MembershipValue
    
    Area 51        12/10/2012     testing site                  Valid       False
          Username="Jsmith"
          Bool="or"
          username="MGordon"
    
    Apollo         12/04/2010     fly to the Moon               Terminated  False
          Username="DKerr"
          bool="and"
          Username="Sremi"
          bool="or"
          Group="ApolloReadOnly"
    
    Deep Impact    12/06/08       Exploring Comet Temple        Achieved    True
            Username="Gblaine"
            Group="SSnype"
            group="Wesson"
            bool="or"
            Computer="Exec-02"
    See the attached project solution.
    Attached Files Attached Files

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured