Reputation: 737
This is the XML
I get from a request:
<ODM xmlns:.....>
<Data DID="Mdid">
<SubjectData SubjectKey="1">
<SRef Location="Loc1"/>
<SEventData SEventID="SID1">
<FormData FormID="FID1">
<ItemGroupData ItemGroupID="IGID1">
<ItemData ItemID="IID1" IsNull="Yes"/>
<ItemData ItemID="IID2" IsNull="Yes"/>
<ItemData ItemID="IID3" IsNull="Yes"/>
<ItemData ItemID="IID4" Value="cvs"/>
</ItemGroupData>
</FormData>
</SEventData>
</SubjectData>
</Data>
<Data DID="Zdid">
<SubjectData SubjectKey="2">
<SRef Location="Loc2"/>
<SEventData SEventID="SID2">
<FormData FormID="FID2">
<ItemGroupData ItemGroupID="IGID2">
<ItemData ItemID="IID11" Value="xcs"/>
<ItemData ItemID="IID12" IsNull="Yes"/>
<ItemData ItemID="IID13" IsNull="Yes"/>
<ItemData ItemID="IID14" Value="zfv"/>
</ItemGroupData>
</FormData>
</SEventData>
</SubjectData>
</Data>
........
</ODM>
How I can store the Items and their Values in a grid from specific Data
, SubjectData
, SEventData
, FormData
, ItemGroupData
or ItemData
?
This is what I have tried for ItemData
but it returns null
:
var xdoc = XDocument.Parse(response.RawXMLString());
var items = xdoc.Descendants("ItemData")
.ToDictionary(i => (string)i.Attribute("ItemID"),
i => (string)i.Attribute("Value"));
Example
Items of "Mdid" Data (will be the same for SubjectKey
== 1, SEventID
= "SID1" etc. But Items of "Zdid" Data will be diferrent because it will probably contain different ItemData
):
ItemID | IsNull | Value
IID1 | Yes |
IID2 | Yes |
......
EDIT
Both solutions unfortunately didn't work... In case it helps here is a sample xml I am working on:link
Upvotes: 0
Views: 92
Reputation: 34421
If it is failing you may have more the one ItemData with same value. Try following :
XDocument doc = XDocument.Load(FILENAME);
Dictionary<string, string> items = doc.Descendants().Where(x => x.Name.LocalName == "ItemData")
.GroupBy(x => (string)x.Attribute("ItemOID"), y => y.Attribute("IsNull") != null ? "Null" : (string)y.Attribute("Value"))
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
//if above fails tgry following
Dictionary<string, List<string>> items2 = doc.Descendants().Where(x => x.Name.LocalName == "ItemData")
.GroupBy(x => (string)x.Attribute("ItemOID"), y => y.Attribute("IsNull") != null ? "Null" : (string)y.Attribute("Value"))
.ToDictionary(x => x.Key, y => y.ToList());
//or use two level dictionary
Dictionary<int, Dictionary<string, string>> items3 = doc.Descendants().Where(x => x.Name.LocalName == "SubjectData")
.GroupBy(x => (int)x.Attribute("SubjectKey"), y => y.Descendants().Where(z => z.Name.LocalName == "ItemData")
.GroupBy(a => (string)a.Attribute("ItemOID"), b => b.Attribute("IsNull") != null ? "Null" : (string)b.Attribute("Value"))
.ToDictionary(a => a.Key, b => b.FirstOrDefault()))
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
Upvotes: 0
Reputation: 118937
Based on the discussion in the comments, this code will parse the ItemData
elements into a list, but will lost the context of whether they came from a Mdid
or Zdid
section:
First a class to hold the item data:
public class ItemData
{
public string ItemID { get; set; }
public string IsNull { get; set; }
public string Value { get; set; }
}
And the Linq to process the XML:
var items = xdoc
.Descendants("Data")
.Where(d => d.Attribute("DID").Value == "Mdid") //These lines can be added
.Descendants("ItemData") //to filter if you need them
.Select(i => new ItemData
{
ItemID = (string)i.Attribute("ItemID"),
IsNull = (string)i.Attribute("IsNull"),
Value = (string)i.Attribute("Value")
});
In case you need to include the namespace, this is how you do it:
XNamespace ns = "http://www.cdisc.org/ns/odm/v1.3";
And then prefix the names with `ns. For example:
.Descendants(ns+"ItemData")
Upvotes: 1