【问题标题】:How to access to different elements of a XML?如何访问 XML 的不同元素?
【发布时间】:2018-06-25 09:20:27
【问题描述】:

我有一个 XML,其中包含有关飞行计划的不同信息。我需要使用“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 我需要执行一些算法。问题是我需要根据指针所在的部分执行不同的功能。

我是 C# 编程新手,我确信存在另一种更好的形式来访问此类数据。

您能帮我按类型访问这些数据吗?

【问题讨论】:

  • “我的程序崩溃”——到底发生了什么?是否抛出异常?
  • 我无法解析您的 XML!你确定它有效吗?
  • @Wheels73 无效。注意未闭合的元素。
  • @SebastianHofmann - 啊是的......对我来说还早!干杯!
  • 您确定&lt;RoutePoints&gt; 没有(默认)命名空间吗?调试器告诉你什么?你也没有展示你是如何得到i:

标签: c# xml xml-parsing


【解决方案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")
        {
        }
    }
}

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

【讨论】:

  • 当指针在: 并检查 FirstOrDefault()?.Value == "RoutePointTakeOff" 程序崩溃因为 NullReferenceException 未处理。
  • 不,除非我们有不同的 xml 文件。 ? 运算符不会抛出。
  • 是的,我没用过?操作员。但这对我不起作用。
【解决方案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();

【讨论】:

  • 这个解决方案只取 XML 文件的属性并把它放在一个列表中,不是吗?我需要获取元素,我需要处理的信息在元素内部。比如在RoutePoint里面我需要用包含的值初始化一些属性。在RoutePointTakeOff里面我需要执行一些算法。问题是我需要根据指针所在的部分执行不同的功能。
  • 您可以将您的代码添加到我的。使用 foreach(结果中的 var 路由){}。您将需要测试是否为空。值将是 id、_ref、类型。您的样本中没有包含任何元素值。如果有元素,则添加 value = (string)x 作为另一行。
【解决方案3】:

试试这个

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

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

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

【讨论】:

    【解决方案4】:

    我在调试,终于发现错误了……

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

    NullReferenceException 未处理

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-04
      • 1970-01-01
      相关资源
      最近更新 更多