简体   繁体   中英

Linq2Xml - how to get nodes and childnodes related

I have xml like this:

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

This code gets only the first item " and " and then generate a exception '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++;
            }

        }

The idea is to get item.arrivalDateTime and item.arrivingCity and its crewMembers.item.employeeId for all the rows. However I do not know how to get the childnodes using linq...us occrring a exception if when try employeeId = x.Element(s + "employeeId").Value....

Result should be something like this:

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

The problem is in your use of Descendants . You're asking for all item descendants of flights elements - which means it will include this:

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

That clearly doesn't have an arrivalDateTime element, hence the problem.

Replacing every call of Descendants to Elements in your sample code fixes the problem... although you're still going to fail if the actual document doesn't have all of the expected data.

SOLVED

we just need to replace that foreach for :

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

            }

        }

Thank you guys....

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM