c# - Parse Xml with same key values -


i working on windows phone 8 application,

i have ui looks :

main item --- has desc , list of subitems key value

main item b --- has desc , list of subitems key value

main item c --- has desc , list of subitems key value

now on click of move next page display description , sub items.

on click of main item a

description of main item a

sub item 1 --- on click of display desc sub item 2 --- on click of display desc

here how xml looks like:

<plist version="1.0">      <dict>         <key>category</key>         <array>             <dict>                 <key>name</key>                 <string>a</string>                 <key>description</key>                 <string>some data</string>                 <key>subitems</key>                 <array>                     <dict>                         <key>description</key>                         <string>some data</string>                         <key>name</key>                         <string>one</string>                     </dict>                     <dict>                         <key>name</key>                         <string>two</string>                         <key>description</key>                         <string>some data</string>                     </dict>                  </array>             </dict>             <dict>                 <key>name</key>                 <string>b</string>                 <key>description</key>                 <string>some data</string>                 <key>subitems</key>                 <array>                     <dict>                         <key>description</key>                         <string>some data</string>                         <key>name</key>                         <string>one</string>                     </dict>                     <dict>                         <key>name</key>                         <string>two</string>                         <key>description</key>                         <string>some data</string>                     </dict>                  </array>             </dict> 

how parse example ?

update

i have solved :

dictionary<string, list<tricks>> plistdata =                     doc.root.element("dict").element("array").elements("dict")                         .select(getvalues)                         .todictionary(v => (string)v["name"],                                       v => v["subitems"]                                       .elements("dict").select(parse).tolist());  static tricks parse(xelement dict)         {             var values = getvalues(dict);              return new tricks             {                 subtitle = (string)values["name"],                 subtitledescription = (string)values["description"]             };         }  static dictionary<string, xelement> getvalues(xelement dict)         {             return dict.elements("key")                        .todictionary(k => (string)k, k => (xelement)k.nextnode);         } 

in above able except maintitle description, can please me correct it.

you trying squeeze 3 pieces of information (a name, description , list of subitems) in datamodel has room 2 items (a key , value).

i provide 2 solutions. 1 'fixes' problem in code , 1 more flexible solution. pick either 1 like

quickfix

the biggest change dictionary no longer returns string fullfledge tricks object.

public dictionary<tricks, list<tricks>> clumsy(xdocument doc) {     var plistdata =         doc             .root             .element("dict")             .element("array")             .elements("dict")             .select( ele => new                      {                     key = parse(ele),                     val = ele.element("array")                            .elements("dict")                            .select(parse).tolist()                 }).todictionary(pair => pair.key,                                 pair => pair.val);     return plistdata; }  static tricks parse(xelement dict) {     var values = getvalues(dict);      return new tricks     {         subtitle = (string)values["name"],         subtitledescription = (string)values["description"]     }; }  static dictionary<string, xelement> getvalues(xelement dict) {     return dict.elements("key")                .todictionary(k => (string)k, k => (xelement)k.nextnode); } 

more flexible solution

assuming have soming menuroot class holds collection of menu items in turn can hold collecion of menu items used following plistparser class return th mentioned class model.

public class plistparser {     public t deserialize<t>(stream stream) t : new()     {         return deserialize<t>(xdocument.load(stream));     }      public t deserialize<t>(string xml) t:new()     {         return deserialize<t>(xdocument.parse(xml));     }      private t deserialize<t>(xdocument doc) t : new()     {         return deserializeobject<t>(             doc.document.             element("plist").             element("dict"));     }      // parse th xml object     private t deserializeobject<t>(xelement dict) t:new()     {         var obj = new t();         var objtype = typeof (t);          // either propertty names or xmlelement values         var map = getmapping(objtype);          // iterate on key elements , match them against         // names of properties of ther class         foreach (var key in dict.elements("key"))         {             var pi = map[key.value];             if (pi != null)             {                 // next node value                 var value = key.nextnode xelement;                 if (value != null)                 {                     // type of value                     switch (value.name.tostring())                     {                         case "array":                             // assume generic list arrays                             // process subelements                             object subitems = invokedeserializearray(                                 pi.propertytype.getgenericarguments()[0],                                 value);                             pi.setvalue(obj, subitems, null);                             break;                         case "string":                             // simple assignment                             pi.setvalue(obj, value.value, null);                             break;                         case "integer":                             int valint;                             if (int32.tryparse(value.value, out valint))                             {                                 pi.setvalue(obj, valint, null);                             }                             break;                         default:                             throw new notimplementedexception(value.name.tostring());                             break;                     }                 }                 else                 {                     debug.writeline("value null");                 }             }             else             {                 debug.writeline(key.value);             }         }         return obj;     }      // map name properyinfo     private static dictionary<string, propertyinfo> getmapping(type objtype)     {         // todo: cache..         var map = new dictionary<string, propertyinfo>();         // iterate on properties find...         foreach (var propertyinfo in objtype.getproperties())         {             // .. if has xmlelementattribute on             var eleattr = propertyinfo.getcustomattributes(                 typeof (xmlelementattribute), false);             string key;             if (eleattr.length == 0)             {                 // ... if doesn't property name our key                 key = propertyinfo.name;             }             else             {                 // ... if elementname given attribute                  // key.                 var attr = (xmlelementattribute) eleattr[0];                 key = attr.elementname;             }             map.add(key, propertyinfo);         }         return map;     }      //http://stackoverflow.com/a/232621/578411     private object invokedeserializearray(type type, xelement value)     {         methodinfo method = typeof(plistparser).getmethod(             "deserializearray",             bindingflags.instance |              bindingflags.invokemethod |              bindingflags.nonpublic);         methodinfo generic = method.makegenericmethod(type);         return generic.invoke(this, new object[] {value});     }      // array handling, returns list     private list<t> deserializearray<t>(xelement array) t:new()     {         var items = new list<t>();         foreach (var dict in array.elements("dict"))         {             items.add(deserializeobject<t>(dict));         }         return items;     }  } 

classmodel

public class menuroot {     public list<tricks> category { get; set; } }  public class tricks {     [xmlelementattribute("name")]     public string subtitle { get; set; }     [xmlelementattribute("description")]     public string subtitledescription { get; set; }     public list<tricks> subitems { get; set; } } 

usage

var parser = new plistparser(); var menu =  parser.deserialize<menuroot>(@"c:\my\path\to\the\plist.xml"); 

Comments

Popular posts from this blog

php - render data via PDO::FETCH_FUNC vs loop -

c++ - OpenCV Error: Assertion failed <scn == 3 ::scn == 4> in unknown function, -

The canvas has been tainted by cross-origin data in chrome only -