如何访问XML的不同元素?

时间:2018-06-25 09:20:27

标签: c# xml xml-parsing

我有一个XML,其中包含有关flightPlan的不同信息。我需要使用“ RoutePoints”标签获取此飞行计划的数据。下面的示例是表示结构的伪代码。 “ +”符号表示该部分可以展开。

    <RoutePoints>
      +<a:anyType z:Id="411" i:type="RoutePointTakeOff">
      +<a:anyType z:Id="472" i:type="RoutePoint">
      +<a:anyType z:Id="518" i:type="RoutePoint">
      <a:anyType z:Ref="349" i:nil="true"/>
      <a:anyType z:Ref="272" i:nil="true"/>
      +<a:anyType z:Id="576" i:type="RoutePoint">
      +<a:anyType z:Id="638" i:type="RoutePointLanding">
    </RoutePoints>

因为我有不同类型的元素,需要处理的元素有所不同。我尝试使用foreach工具访问此元素,例如以下示例:

foreach ( var routes in document.Descendants("RoutePoints") ){
    foreach ( var points in routes.Elements() ) {
        if ( points.Attributes(i+"type").First().Value == "RoutePoint") {
            //Processing..
        }
        if ( points.Attributes(i+"type").First().Value == "RoutePointTakeOff") {
            //Processing..
        }
        if ( points.Attributes(i+"nil").First().Value == "true") {
            //Processing..
        }
        if ( points.Attributes(i+"type").First().Value == "RoutePointLanding") {
            //Processing..
        }
    }
}

例如,如果if子句检查属性以比较该值且该值不存在,则检查值RoutePointTakeOff且该值不存在,因为此值在第一行中,而现在在第二行中进行检查。

我需要获取元素,我需要处理的信息在元素内部。例如,在RoutePoint内部,我需要使用包含的值来初始化一些属性。在RoutePointTakeOff内部,我需要执行一些算法。问题是我需要根据where指针所在的部分执行不同的功能。

我是C#的新编程人员,并且可以肯定存在另一种更好的形式来访问此类数据。

您能帮助我按类型访问此数据吗?

4 个答案:

答案 0 :(得分:2)

尝试以下操作:

           XDocument doc = XDocument.Load(FILENAME);

            var results = doc.Descendants().Where(x => x.Name.LocalName == "anyType")
                .Select(x => new {
                    id = x.Attributes().Where(z => z.Name.LocalName == "Id").Select(z => (int)z).FirstOrDefault(),
                    _ref = x.Attributes().Where(z => z.Name.LocalName == "Ref").Select(z => (int)z).FirstOrDefault(),
                    type = x.Attributes().Where(z => z.Name.LocalName == "type").Select(z => (string)z).FirstOrDefault()
                }).ToList();

答案 1 :(得分:1)

如果您使用FirstOrDefault而不是First,则代码按预期工作,可以处理每个元素:

foreach (var routes in document.Descendants("RoutePoints"))
{
    foreach (var points in routes.Elements())
    {
        if (points.Attributes(i + "type").FirstOrDefault()?.Value == "RoutePoint")
        {
        }
        if (points.Attributes(i + "type").FirstOrDefault()?.Value == "RoutePointTakeOff")
        {
        }
        if (points.Attributes(i + "nil").FirstOrDefault()?.Value == "true")
        {
        }
        if (points.Attributes(i + "type").FirstOrDefault()?.Value == "RoutePointLanding")
        {
        }
    }
}

请注意,如果找不到匹配的属性,请使用?作为内联null检查。

答案 2 :(得分:1)

尝试这个

public List<DataAttr> GetDataAttribute(XDocument xDocument)
    {
        var dataAttr = new List<DataAttr>();
        foreach (var route in xDocument.Descendants("RoutePoints"))
        {
            foreach (var point in route.Elements())
            {
                if (point.HasElements)
                {
                    dataAttr.AddRange(_getAttributeValues(point.Attributes()));
                }
            }
        }
        return dataAttr;
    }

    private static IEnumerable<DataAttr> _getAttributeValues(IEnumerable<XAttribute> attributes)
    {
        return attributes.Select(x => new DataAttr()
        {
            Name = x.Name.LocalName,
            Value = x.Value
        });
    }
public class DataAttr
{
    public string Name { get; set; }
    public string Value { get; set; }
}

在此之后,您可以按名称对数据组进行排序。

如果使用此代码,则不受属性名称的限制。 祝你好运。

答案 3 :(得分:0)

我正在调试,最后发现错误...

我正在评估属性“类型”,该属性在第4-5行中不存在。这导致了错误。更具体地说:

  

未处理NullReferenceException

毕竟我使用的是null控件,现在它可以工作了。

foreach ( var routes in document.Descendants("RoutePoints") ){
    foreach ( var points in routes.Elements() ) {
        if ( points.Attributes( i + "type").FirstOrDefault != null ){
             if ( points.Attributes(i+"type").First().Value == "RoutePoint") {
                //Processing..
             }
             if ( points.Attributes(i+"type").First().Value == "RoutePointTakeOff") {
                //Processing..
             }
             if ( points.Attributes(i+"type").First().Value == "RoutePointLanding") {
                //Processing..
             }
        } else {
             // Will execute this in rows 4-5    
        }
    }
}