Working with XML in Silverlight and bonus – generic Property Bag implementation

I believe, that if you are in programming, you know what Property Bag is. This is handy generic class, that can "eat" poor-known structure and process a list with all this information. You often can access properties of the parent class by name.

Why this good? Property Bag provides very intuitive way to access data. This type safe collection, that has not single type, but can be filled with data of different types. Let’s see an example of such data.

     <vCard>
       <FullName>
       <FamilyName>Crystal</FamilyName>
       <GivenName>Corky</GivenName>
       </FullName>
       <Title>Computer Officer Class 3</Title>
       <Role>Programmer</Role>
       <Phone>+61 7 555 5555</Phone>
       <Email>corky@qqqfoo.com</Email>
       <Organization>
       <OrganizationName>qqqfoo.com Pty Ltd</OrganizationName>
       <OrganizationUnit> Commercialisation Division </OrganizationUnit>
       </Organization>
       <Address>
       <Street>111 Lake Drive</Street>
       <Locality>WonderCity </Locality>
       <Pcode>55555</Pcode>
       <Country>Australia</Country>
       </Address>
       </vCard> 

 

Well, in order to get any information from such file, you need to parse XML and know it’s structure or DTD. If someone will change the file and remove FullName tag, for example, all your program often have to be rewritten. So, we’re implementing PropertyBag helper call to take care on such cases. Here the simple implementation of such class in C#

    public class PropertyBag : List<KeyValuePair<string, string>>
       { 

 public PropertyBag (XmlDocument source)
       { 

 //((WaitCallback)delegate
       //{
       fillTheBag(source.ChildNodes);
       //}).BeginInvoke(null, null, null);
       } 

 void fillTheBag(XmlNodeList root)
       { 

 for (int i = 0; i < root.Count; i++)
       { 

 if (root[i].ChildNodes.Count > 0)
       { 

 fillTheBag(root[i].ChildNodes); 

 } 

 else
       {
       base.Add(new KeyValuePair<string, string>(root[i].ParentNode.Name, root[i].InnerText));
       } 

 } 

 } 

 public string GetPropertyValue(string property)
       { 

 for (int i = 0; i < base.Count; i++)
       { 

 if (base[i].Key == property)
       return base[i].Value;
       } 

 return string.Empty;
       } 

 } 

 

Now, you can create PropertyBag by using easy constructor with XmlDocument as parameter and call any of internal information, found in source XML as bag["FirstName"].

This is very cool, but when we want to implement such approach in Silverlight, we will find, that there is no XmlDocument there, as well as no DOM at all. The only thing, you can use is XmlReader, that reads information from string stream and parses in on the fly. So how to know, when we have nested elements, how to know, that we have types of data. Let me introduce you SilverPropertyBag, useful class to read information from remote XML file and put it into property bag.

     public class SilverPropertiesBag : List<KeyValuePair<string, string>>
       { 

 public SilverPropertiesBag(string xmlPath)
       { 

 XmlReaderSettings settings = new XmlReaderSettings();
       settings.ConformanceLevel = ConformanceLevel.Fragment;
       settings.IgnoreWhitespace = true;
       settings.IgnoreComments = true;
       settings.IgnoreProcessingInstructions = true; 

 try
       {
       HttpWebRequest request = new BrowserHttpWebRequest(new Uri(xmlPath));
       HttpWebResponse response = request.GetResponse();
       Stream content = response.GetResponseStream(); 

 XmlReader reader = XmlReader.Create(content, settings);
       reader.MoveToFirstAttribute(); 

 fillTheBag(reader); 

 } 

 catch {}
       } 

 void fillTheBag(XmlReader root)
       { 

 int depth = root.Depth;
       KeyValuePair<string, string> last = new KeyValuePair<string, string>();
       while (root.Read())
       { 

 switch (root.NodeType)
       { 

 case XmlNodeType.Text:
       last = new KeyValuePair<string, string>(root.Name, root.Value);
       break;
       case XmlNodeType.EndElement:
       if (last.Key == string.Empty && last.Value != string.Empty)
       { 

 last = new KeyValuePair<string, string>(root.Name, last.Value);
       base.Add(last);
       last = new KeyValuePair<string,string>();
       } 

 if (depth > root.Depth)
       return;
       break; 

 } 

 if (root.IsEmptyElement || root.EOF) return;
       else if (root.IsStartElement())
       { 

 string name = root.Name; 

 if (root.HasAttributes)
       { 

 while (root.MoveToNextAttribute())
       { 

 base.Add(new KeyValuePair<string, string>(root.Name, root.Value));
       } 

 root.Read(); 

 if (root.NodeType == XmlNodeType.CDATA && root.Value.Length == 0)
       { 

 root.Read(); 

 } 

 if (root.NodeType == XmlNodeType.Text && root.ValueType == typeof(string) && root.Value != string.Empty)
       { 

 base.Add(new KeyValuePair<string, string>(name, root.Value));
       } 

 if (root.NodeType == XmlNodeType.EndElement && root.Name.Equals(name))
       { 

 root.Read(); 

 if (root.Depth < depth)
       return;
       else
       continue; 

 } 

 if (root.IsStartElement())
       { 

 if (root.Depth > depth)
       fillTheBag(root); 

 else
       continue;
       } 

 root.Read(); 

 } 

 } 

 } 

 } 

 public string GetPropertyValue(string property)
       { 

 for (int i = 0; i < base.Count; i++)
       { 

 if (base[i].Key == property)
       return base[i].Value;
       } 

 return string.Empty;
       } 

 } 

 

Well. It’s pretty easy to understand how it works, but it’s extremely useful for  any of your Silverlight projects. Happy programming.

You may also be interested with:

  1. RSA private key import from PEM format in C#

10 Responses to “Working with XML in Silverlight and bonus – generic Property Bag implementation”

  1. Tamir Khason Says:

    Take a look here blogs.microsoft.co.il/…/networking-raw-sockets-in-silverlight-and-wpf-messaging-in-general.aspx. As always, you can use raw sockets :)

  2. Manu Says:

    Thanks for the reply.

    I tried WebRequest and WebResponse class, but it gvies same error.

  3. Tamir Khason Says:

    Manu, it’s HttpWebRequest/WebRequest now in SL2.0

  4. manu Says:

    'System.Net.BrowserHttpWebRequest' is inaccessible due to its protection level

  5. re: Working with XML in Silverlight and bonus - generic Property … | Burn Your Bonus Says:

    Pingback from  re: Working with XML in Silverlight and bonus – generic Property &#8230; | Burn Your Bonus

  6. ... Says:

    Thanks a lot. You helped me much

  7. ... Says:

    ..was just passing by.. good work

  8. ... Says:

    me like THAT!:)

  9. Hank Lynch Says:

    Hey Tamir,

    That’s an awesome snippet man, thanks for the idea, I’m sure I’ll be using it.

  10. Sammie Rochon Says:

    Nice articles, but I am not clear about the point you mentioned about how to distinguish fake and real cheap louis vuitton.

Leave a Reply

Recommended

 


Sponsor


Partners

WPF Disciples
Dreamhost
Code Project
Switched to Better Place

Together