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
Post a Comment