c#解析XML并将节点存储到网格

时间:2018-05-08 10:48:35

标签: c# xml xml-parsing

这是我从请求中获得的XML

<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>

如何将项目及其值存储在特定DataSubjectDataSEventDataFormDataItemGroupData或{{1}的网格中}}?

这是我为ItemData尝试的内容,但它返回ItemData

null

示例

&#34; Mdid&#34;数据(var xdoc = XDocument.Parse(response.RawXMLString()); var items = xdoc.Descendants("ItemData") .ToDictionary(i => (string)i.Attribute("ItemID"), i => (string)i.Attribute("Value")); == 1,SubjectKey =&#34; SID1&#34;等等相同但是&#34; Zdid&#34;数据的项目会有所不同,因为它会可能包含不同的SEventID):

ItemData

修改

不幸的是,这两个解决方案都不起作用......如果它有帮助,我正在处理的是一个示例xml:link

2 个答案:

答案 0 :(得分:1)

根据评论中的讨论,此代码会将ItemData元素解析为列表,但会丢失它们是来自Mdid还是Zdid部分的上下文:

首先是一个保存项目数据的类:

public class ItemData
{
    public string ItemID { get; set; }
    public string IsNull { get; set; }
    public string Value { get; set; }
}

Linq处理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")
   }); 

如果您需要包含命名空间,请按以下步骤操作:

XNamespace ns = "http://www.cdisc.org/ns/odm/v1.3";

然后用`ns为名称加前缀。例如:

.Descendants(ns+"ItemData") 

答案 1 :(得分:0)

如果失败,您可能会有更多具有相同值的ItemData。请尝试以下方法:

           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());