Linq2Xml - 如何获取节点和子节点相关

时间:2012-10-04 16:28:04

标签: c# xml linq-to-xml

我有这样的xml:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
  <supplyCrew xmlns="http://site.ddf.com">
     <login>
        <login>XXXX</login>
        <password>XXXX</password>
     </login>
     <flightInformation>
        <flights>
           <item>
              <arrivalDateTime>2010-11-08T22:48:00.000Z</arrivalDateTime>
              <arrivingCity>ORD</arrivingCity>
              <crewMembers>
                 <item>
                    <employeeId>020040</employeeId>
                    <isDepositor>Y</isDepositor>
                    <isTransmitter>N</isTransmitter>
                 </item>
                 <item>
                    <employeeId>09000</employeeId>
                    <isDepositor>N</isDepositor>
                    <isTransmitter>Y</isTransmitter>
                 </item>
              </crewMembers>
           </item>
           <item>
              <arrivalDateTime>2010-11-08T20:29:00.000Z</arrivalDateTime>
              <arrivingCity>JFK</arrivingCity>
              <crewMembers>
                 <item>
                    <employeeId>0538</employeeId>
                    <isDepositor>Y</isDepositor>
                    <isTransmitter>N</isTransmitter>
                 </item>
                 <item>
                    <employeeId>097790</employeeId>
                    <isDepositor>N</isDepositor>
                    <isTransmitter>Y</isTransmitter>
                 </item>
              </crewMembers>
           </item>
        </flights>
     </flightInformation>
  </supplyCrew>

此代码仅获取第一个项“and”,然后生成异常'System.NullReferenceException'。

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Xml.Linq;
using System.Text;
using System.Xml;
using System.Data.SqlClient;
using System.Data;
using System.IO;

namespace ConsoleApplication1
{

class Program
{ 

  static void Main(string[] args)
    {


        XElement doc = XElement.Load("U:/Crew.xml");
        XNamespace e = "http://schemas.xmlsoap.org/soap/envelope/";
        XNamespace s = "http://site.ddf.com";

                   var flights = doc.Elements(e + "Body")
        .Elements(s + "supplyCrew")
        .Elements(s + "flightInformation")
        .Elements(s + "flights")
        .Elements(s + "item")
        .Select(
        flight_item => new
        {
            //Anonymous Type
            arrivalDateTime = flight_item.Element(s + "arrivalDateTime").Value,
            arrivingCity = flight_item.Element(s + "arrivingCity").Value,
            crewmember = flight_item.Elements(s + "crewMembers").Elements(s + "item"),

        }
        );


        int index = 1;
        foreach (var flight_item in flights)
        {

            Console.Write('\n'+"New flight item:"+'\n');
            Console.Write('\t'+flight_item.arrivalDateTime + '\n');
            Console.Write('\t'+flight_item.arrivingCity + '\n');

            foreach (var item in flight_item.crewmember)
            {
                var employeeId = item;//crewmember.Elements(s + "item").Elements("employeeId");
                Console.Write("\t  "+employeeId);
                Console.Write('\n');
                //index++;
            }

        }

我们的想法是为所有行获取item.arrivalDateTime和item.arrivingCity及其crewMembers.item.employeeId。但是,我不知道如何使用linq获取子节点...如果尝试employeeId = x.Element(s +“employeeId”),我们会发现异常。值....

结果应该是这样的:

  

2010-11-08T22:48:00.000Z; ORD; 020040

     

2010-11-08T22:48:00.000Z; ORD; 09000

     

2010-11-08T20:29:00.000Z; JFK; 0538

     

2010-11-08T20:29:00.000Z; JFK; 097790

2 个答案:

答案 0 :(得分:3)

问题在于您使用Descendants。您要求item元素的所有flights个后代 - 这意味着它将包含此内容:

<item>
   <employeeId>020040</employeeId>
   <isDepositor>Y</isDepositor>
   <isTransmitter>N</isTransmitter>
</item>

显然没有arrivalDateTime元素,因此存在问题。

在示例代码中替换DescendantsElements的每次调用都可以解决问题......如果实际文档没有所有预期的数据,您仍然会失败。

答案 1 :(得分:0)

<强>解决

我们只需要替换那个foreach:

        foreach (var flight_item in l_flights)
        {

            Console.Write('\n'+"New flight item:"+'\n');
            Console.Write('\t'+flight_item.arrivalDateTime + '\n');
            Console.Write('\t'+flight_item.arrivingCity + '\n');

            foreach (var item in flight_item.crewmember)
            {
                var employeeId = item.Element(s + "employeeId").Value;
                var isDepositor = item.Element(s + "isDepositor").Value;
                var isTransmitter = item.Element(s + "isTransmitter").Value;

                Console.Write("\t  " + employeeId + "\n");
                Console.Write("\t  " + isDepositor + "\n");
                Console.Write("\t  " + isTransmitter + "\n");

            }

        }

谢谢你们......