读取XML节点

时间:2014-06-18 14:35:48

标签: c# asp.net xml linq-to-xml

我有以下XML文件。我试图读取dept元素的startDate节点,但不想读取任何其他子元素的“startDate”节点,如“DeptRoles”。

<dept operationalStatus="active" primaryRole="Admin" depChangeDate="20130420">      
    <startDate type="legal">20130401</startDate>
    <endDate type="legal"></endDate>
    <startDate type="operational">20130320</startDate>
    <endDate type="operational"></endDate>  
    <DeptRoles>         
        <DeptRole name="Other dept" status="active">
            <startDate type="legal">20130401</startDate>
            <endDate type="legal"></endDate>
            <startDate type="operational">20130320</startDate>
            <endDate type="operational"/>
            <isPrimary/>                
        </DeptRole>
    </DeptRoles>
</dept>

这是我的c#代码。这段代码也得到了我不想要的DeptRole startDate元素。

public static List<organisation> Getorgdata(string data)
    {
        List<organisation> listorgdata = new List<organisation>();
        XmlReader xmlReader = XmlReader.Create(new StringReader(data));
        while (xmlReader.Read())
        {
            if (xmlReader.NodeType == XmlNodeType.Element)
            {
                organisation record = new organisation();
                if (xmlReader.HasAttributes && xmlReader.Name == "dept")
                {
                    record.orgOperationalStatus = xmlReader.GetAttribute("operationalStatus");
                    record.orgLegalStatus = xmlReader.GetAttribute("legalStatus");
                }
                else if (xmlReader.Name == "name")
                {
                    record.orgName = xmlReader.ReadElementString("name");
                }

                else if (xmlReader.Name == "startDate" || xmlReader.Name == "endDate")
                {
                    if (xmlReader.GetAttribute("type") == "legal")
                    {
                        record.orgLegalStartDate = xmlReader.ReadElementString("startDate");
                        record.orgLegalEndDate = xmlReader.ReadElementString("endDate");
                    }
                    else if (xmlReader.GetAttribute("type") == "operational")
                    {
                        record.orgOperationalStartDate = xmlReader.ReadElementString("startDate");
                        record.orgOperationalEndDate = xmlReader.ReadElementString("endDate");
                        listorgdata.Add(record);
                    }
                }
            }
        }
        return listorgdata;
    }

4 个答案:

答案 0 :(得分:1)

我会使用LINQ to XML(正如其他人所建议的那样)。下面是与您发布的代码有些匹配的示例代码 - 代码说明如下。

public static List<organisation> Getorgdata(string data)
{

    List<organisation> listorgdata = new List<organisation>();
    XDocument xDoc = XDocument.Parse(data);

    listorgdata = xDoc.Root.Elements("dept")
                  .Select(x => new organisation()
                  {
                      orgOperationalStatus = (string)x.Attribute("operationalStatus"),
                      orgLegalStartDate = (string)x.Elements("startDate")
                                          .Where(x1 => (string)x1.Attribute("type") == "legal")
                                          .First(),
                      orgOperationalStartDate = (string)x.Elements("startDate")
                                                .Where(x1 => (string)x1.Attribute("type") == "operational")
                                                 .First()
                  }).ToList();

     return listorgdata;
}    

上面代码的第一件事就是使用XDocument.Parse方法将XML加载到XDocument中。

然后,查询解析XML文档并返回已填充的organization个对象的列表。它就是这样的。

  1. 获取所有<dept>元素(以及子元素)。
  2. 使用每个<dept>元素,创建organisation的新实例,并指定&#34; operationalStatus&#34;的值。属性为operationalStatus的{​​{1}}属性。 organisation强制转换将优雅地处理指定属性不存在的情况。
  3. 对于法定开始日期,我们对(string)元素的<startDate>个子元素进行查询,获取第一个具有属性&#34;类型&#34;等于&#34; legal&#34;。
  4. 对于操作开始日期,我们对第3个进行类似的查询,但它正在寻找&#34;操作&#34;。
  5. 通过调用<dept>扩展程序将IEnumerabale<T>结果转换为列表。
  6. 这可能不是最有效的,它并不涵盖您原始代码中的所有属性,但它至少应该让您朝着正确的方向前进。例如,如果你想获得&#34; primaryRole&#34;属性,您只需在.ToList()块中添加以下行:

    new organisation()

    如果您需要来自orgPrimaryRole = (string)x.Attribute("primaryRole"), 的数据,那么您可以获得该数据,但它需要更多参与。

    如果您更喜欢查询语法而不是方法语法,它将如下所示:

    <DeptRoles>

答案 1 :(得分:0)

如果我添加 CATALOG

<CATALOG>
<dept operationalStatus="active" primaryRole="Admin" depChangeDate="20130420">      
<startDate type="legal">20130401</startDate>
<endDate type="legal"></endDate>
<startDate type="operational">20130320</startDate>
<endDate type="operational"></endDate>  
<DeptRoles>         
<DeptRole name="Other dept" status="active">
<startDate type="legal">20130401</startDate>
<endDate type="legal"></endDate>
<startDate type="operational">20130320</startDate>
<endDate type="operational"/>
<isPrimary/>                
</DeptRole>
</DeptRoles>
</dept>
</CATALOG>

使用System.Xml.Linq;你可以获得你的清单:

XElement myXML = XElement.Load(@"C:\Users\User\Desktop\myXML.xml");
var deptDescendantsList = (from ep in myXML.Descendants("dept")
                           select ep.Elements("startDate")).ToList();

答案 2 :(得分:0)

我不确定如何创建完全符合您需求的查询。 尝试将此查询附加到您的需求。 http://msdn.microsoft.com/en-us/library/bb387061.aspx包含有关linq2xml查询的一些信息

XmlReader xmlReader = XmlReader.Create(new StringReader(data));

XDocument d = XDocument.Load(xmlReader);

var startDates = from item in d.Root.Descendants()
                where item.Name == "startDate" && item.Parent.Name == "dept" && item.Parent.Attribute("deptid").Value == "anynumber"
                select item;

        // iterate over the startDates and do your magic

答案 3 :(得分:0)

试试这个:

var readSpecific =来自xd.Descendants中的一个(&#34;部门&#34;)

                      select new
                      {

                          LegalStartDate = a.Element("dept").Elements("startDate").First(cc => cc.Attribute("type").Value == "legal").Value,
                          LegalEndDate = a.Element("dept").Elements("endDate").First(cc => cc.Attribute("type").Value == "legal").Value,

                          OperationalStartDate = a.Element("dept").Elements("startDate").First(cc => cc.Attribute("type").Value == "operational").Value,
                          OperationEndDate = a.Elements("dept").Elements("endDate").First(cc => cc.Attribute("type").Value == "operational").Value
                       };