i have class goes , gets data database , gets xml data in form of hierarchical data.
below sample of data:
<securitygroups> <securitygroup> <id>1</id> <name>view</name> </securitygroup> <securitygroup> <id>2</id> <name>fill</name> <securityusers> <securityuser> <securityid>2</securityid> <userid>2</userid> <username>fill</username> </securityuser> <securityuser> <securityid>2</securityid> <userid>3</userid> <username>fillone</username> </securityuser> <securityuser> <securityid>2</securityid> <userid>4</userid> <username/></securityuser> </securityusers> </securitygroup> <securitygroup> <id>3</id> <name>update</name> <securityusers> <securityuser> <securityid>3</securityid> <userid>5</userid> <username>update</username> </securityuser> <securityuser> <securityid>3</securityid> <userid>6</userid> <username>updateone</username> </securityuser> </securityusers> </securitygroup> <securitygroup> <id>4</id> <name>admin</name> <securityusers> <securityuser> <securityid>4</securityid> <userid>1</userid> <username>jtays</username> </securityuser> </securityusers> </securitygroup>
which works great! now, have class uses reflection convert xml models going use in treeview. below entire class.
the models are:
[xmlrootattribute(namespace = "", isnullable = false)] public class securitygroup { [xmlelementattribute(form = xmlschemaform.unqualified)] public int id { get; set; } [xmlelementattribute(form = xmlschemaform.unqualified)] public string name { get; set; } [xmlelementattribute("securityuser", form = xmlschemaform.unqualified)] public list<securityuser> securityusers { get; set; } } public class securityuser:ientity { [xmlelement(form = xmlschemaform.unqualified)] public int securityid { get; set; } [xmlelementattribute(form = xmlschemaform.unqualified)] public int userid { get; set; } [xmlelementattribute(form = xmlschemaform.unqualified)] public string username { get; set; } public int id { get; set; } }
here class converts.
public class adminmanager : iadminservice { public ienumerable<securitygroup> securitygroups() { ienumerable<securitygroup> list = null; xmldocument xmldoc = new xmldocument(); using (var c = new fmcontext()) { var xmldata = c.database.sqlquery<string>("allsecurtyusersproc").firstordefault(); if (xmldata != null) { xmldoc.loadxml(xmldata); list = convertxmltoclass<securitygroup>(xmldoc, "/securitygroups/securitygroup"); } } return list; } public static ienumerable<t> convertxmltoclass<t>( xmldocument doc, string nodestring) t:class, new() { var xmlnodes = doc.selectnodes(nodestring); list<t> list = new list<t>(); foreach (xmlnode node in xmlnodes) { var item = getnewitem<t>(node); list.add(item); } return list; } public static t getnewitem<t>(xmlnode node) t:class, new() { var type = typeof (t); var item = new t(); var properties = type.getproperties(); foreach (var property in properties) { var propertytype = property.propertytype; var propertyname = property.name; object value = null; if (isenumerable(property)) { value = getnodecollectionvalue(property,node); } else { value = getnodevalue(node, propertyname); } if (value!=null) { property.setvalue(item, convert.changetype(value, propertytype), null); } } return item; } private static object getnodecollectionvalue(propertyinfo property, xmlnode node) { var doc = new xmldocument(); var itemtype = property.propertytype.generictypearguments[0]; var xml = $"<{property.name}><{itemtype.name}>{node.innerxml}</{itemtype.name}></{property.name}>"; doc.loadxml(xml); if (itemtype != null) { var type = typeof (adminmanager); var methodinfo = type.getmethod("convertxmltoclass"); if (methodinfo!=null) { var method = methodinfo.makegenericmethod(itemtype); if (method != null) { object[] args = {doc, property.name}; object result = method.invoke(null, args); return result; } } } return new object(); } private static bool isenumerable(propertyinfo property) { var type = property.propertytype; return typeof (ienumerable).isassignablefrom(type) && type.isgenerictype; } private static object getnodevalue(xmlnode node, string nodename) { var = node[nodename]?.innertext; return ?? null; } }
okay, issue. problem when converts doesn't correct data securtyusers
classes adds them object, null or 0. can me figure out went worng?
first: example xml doesn't include closing tag </securitygroups>
.
in getnodecollectionvalue pass property.name
shouldn't property.name + "/" + itemtype.name
because want access children of node?
additionally node.innerxml
not traversed, pass same node again , again.
i highly recommend using .net xml deserializer instead of reinventing wheel.
generate xml schema xml example. afterwards create .net classes xsd. pass xml server stringreader , deserialize using reader. access securitygroup
class instance.
[update] show usage
create xml schema either manually or using xsd.exe
(you need windows sdk). see examples.
- create sample.xml file, content example
- locate , run xsd tool
xsd sample.xml /outputdir:xmlserialization
- a
.xsd
file should generated, may want modify element types- for example securitygroup.id maybe auto-generated
xs:string
, change i.e.xs:int
- or remove
minoccurs="0"
@ securityuser.userid if know property set - you maybe have fix securitygroup.securityusers from
- for example securitygroup.id maybe auto-generated
<xs:element name="securityusers" minoccurs="0" maxoccurs="unbounded"> <xs:complextype> <xs:sequence> <xs:element name="securityuser" minoccurs="0" maxoccurs="unbounded">
to
<xs:element name="securityusers" minoccurs="0"> <xs:complextype> <xs:sequence> <xs:element name="securityuser" maxoccurs="unbounded">
- run xsd tool using xsd
xsd sample.xsd /outputdir:xmlserialization /c
- a
.cs
file should generated, verify- i needed fix xsd manually because i.e. securitygroup.securityuser generated 2-dim array
- use auto-generated classes in project / script
- create xmlserializer - see example - , deserialize xml string, access data afterwards
securitygroups deserialized; var serializer = new system.xml.serialization.xmlserializer(typeof(securitygroups)); using (var stringreader = new system.io.stringreader(xmldata)) { deserialized = serializer.deserialize(stringreader) securitygroups; }
- see manually fixed xsd here, verified working sample data
Comments
Post a Comment