winforms - Flatten XML to DataGridView using C#/Linq -
there many questions out there, 1 quite unique can assure you! need generic solution flatten xml data 2 column grid (field, value) real challenge hierarchy of xml data different each response!
this audit data stored in database in xml format, cannot change structure of these responses need handle hierarchy possible , display results user in simple grid.
here sample of xml structure:
<xml> <results> <resultsdto> <reportid>173601</reportid> <results> <displayname>item 1</displayname> <someparameter>blahblah</someparameter> <hidden>false</hidden> <values> <value>10</value> <resulttype>percentage</resulttype> </values> <values> <value>some.pdf</value> <resulttype>pdf</resulttype> </values> <values> <value>findings of item 1</value> <resulttype>findings</resulttype> </values> </results> <results> <displayname>item 2</displayname> <someparameter>blahblah</someparameter> <hidden>false</hidden> <values> <value>20</value> <resulttype>percentage</resulttype> </values> <values> <value/> <resulttype>pdf</resulttype> </values> <values> <value>findings of item 2</value> <resulttype>findings</resulttype> </values> </results> <reporttexts> <value/> <resulttype>history</resulttype> </reporttexts> <reporttexts> <value>some info here.</value> <resulttype>information</resulttype> </reporttexts> </resultsdto> </results> </xml>
as can see xml there "resulttype" , "value" @ same level, need way iterate through xml without defining hardcoded paths (xml/results/resultsdto/results/values/) find these resulttypes , values @ level , handle few special rules data.
i'm trying these values gridview output this:
[field], [value] item 1 - percentage, 10 item 1 - findings, findings of item 1 item 2 - percentage, 20 item 2 - findings, findings of item 2 history, null information, info here.
here current code displaying half of i'm trying achieve:
xdocument doc = xdocument.load(@"xmlfile1.xml"); var query = c in doc.descendants("xml").elements("results").elements("resultsdto").elements("results").elements("values").where(n => n.element("resulttype").value != "pdf") select new { field = c.parent.element("displayname") == null ? c.element("resulttype").value : c.parent.element("displayname").value + " - " + c.element("resulttype").value, value = c.element("value").value }; datagridview1.datasource = query.tolist();
i'm suppressing "pdf" resulttype showing , appending displayname resulttype if exists in parent! not other nodes.
this getting values under xml/results/resultsdto/results/values/ , not values within xml/results/resultsdto/reporttexts.
any appreciated! thanks.
you're right part. need is:
- union descendants of reporttexts elements well.
- descendants don't need traverse path. can give starting path.
use following query:
var query = c in doc.descendants("values").union(doc.descendants("reporttexts")).where(n => n.element("resulttype").value != "pdf") select new { field = c.parent.element("displayname") == null ? c.element("resulttype").value : c.parent.element("displayname").value + " - " + c.element("resulttype").value, value = c.element("value").value // can replace "" null here };
output follows:
[field], [value] item 1 - percentage, 10 item 1 - findings, findings of item 1 item 2 - percentage, 20 item 2 - findings, findings of item 2 history, "" information, info here.
Comments
Post a Comment