Parsing the XML in C#

本文关键字:in XML the Parsing | 更新日期: 2023-09-27 18:06:52

我正在从expedia API获取航班详细信息,请查看下面的XML格式链接。

结果输出包含Rateinfo然后flight details作为单独的节点,并且Rateinfo和flightsegment之间没有关系。通常情况下,我将XML加载到数据集并使用数据集填充记录,但在这种情况下,费率和航班段之间没有关系,我将如何在c#中解析这个XML。我需要向用户显示航段和相应的费率。

http://api.ean.com/ean-services/rs/air/200919/xmlinterface.jsp?cid=55505&resType=air&intfc=ws&apiKey=fc9hjrvrur9vr4y2dqa249w4&xml=<AirSessionRequest method="getAirAvailability"><AirAvailabilityQuery><originCityCode>MCI</originCityCode><destinationCityCode>CLT</destinationCityCode><departureDateTime>09/01/2011 01:00 AM</departureDateTime><returnDateTime>09/04/2011 01:00 AM</returnDateTime><fareClass>Y</fareClass><tripType>R</tripType><Passengers><adultPassengers>2</adultPassengers></Passengers><xmlResultFormat>1</xmlResultFormat><searchType>2</searchType></AirAvailabilityQuery></AirSessionRequest>

Parsing the XML in C#

像上文提到的那样使用LINQ to XML可能会有所帮助。您可以使用LINQ分解XML并一次处理一组费率信息和航班段。如果您使用匿名类型,您可以在一个费率信息和相关航段之间建立自己的连接,然后将其存储在数据库中。

这里有一个粗略的例子,让你沿着这条路走下去:

XDocument xDoc = new XDocument();
xDoc = xDoc.Parse(responseXML); // Parse will take a string and load the XDocument with it
                                // You can also use Load to load from a file, StreamReader, etc.
// First, grab a collection of all the AirAvailabilityReply
var airAvailability = from x in xDoc.Descendants("AirAvailabilityReply")
                      select x;
// Now loop through each of the query results in the collection
foreach (var available in airAvailability)
{
    // Get the rate info
    var rates = from r in available.Descendants("RateInfo")
                select new RateInfo {
                    NativeBaseFare = r.Element("nativeBaseFare").Value,
                    NativeTotalPrice = r.Element("NativeTotalPrice").Value,
                    // etc
                };
    // Get the flight segment info
    var segments = from s in available.Descendants("FlightSegment")
                   select new FlightSegment {
                       SegmentOutgoing = s.Element("segmentOutgoing").Value,
                       AirlineCode = s.Element("airlineCode").Value,
                       // etc
                   };
    // Now you can take RateInfo (should only be one) and the FlightSegments (should be a collection of FlightSegments) and put them into your database.
}

在上面的例子中,我假设你有两个类(RateInfo和FlightSegment),你将用XML中的相应值填充属性。

这可能不是最有效的示例,但希望它能让您了解如何使用LINQ to XML解决这个问题。

我认为在c#中解析xml的基本而强大的方法是Linq2XML。它有非常容易使用的方法,请检查下面的答案:

数据集表示关系数据比xml所表示的层次数据容易得多,这可能是问题的症结所在。

Linq2Xml是一种选择,或者您可以创建一组可序列化的类,并将xml反序列化为类的实例,这样您就可以使用foreach迭代这些类,或者对它们使用linq。

我并不是说这是做您需要的事情的最好方法,但是它相对整洁,并且您不需要处理xml,只需要处理类实例。我用您提供的xml测试了它,它工作得很好,尽管我确实认为Linq2Xml方法可能性能更高-虽然不是100%确定。

假设您的xml在一个名为sXmlResult:

的变量中
public class Test
{
    public void Run()
    {
        //Load the xml and serialize it into instances of our classes
        System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(AirAvailabilityResults));
        System.IO.StringReader sr = new System.IO.StringReader(sXmlResult);
        AirAvailabilityResults results = (AirAvailabilityResults)ser.Deserialize(sr);
        //Now we can access all the data like we would any other object.
        foreach (AirAvailabilityReply reply in results.AirAvailabilityReply)
        {
            double dNativeBaseFare = reply.RateInfo.nativeBaseFare;
            foreach (FlightSegment segment in reply.FlightSegment)
            {
                int iFlightNumber = segment.flightNumber;
            }
        }
    }
}
//Create the seriealizable classes to represent the xml.  
//I created these by infering the schema from the xml.  These classes may need some changes, if 
//they don't exactly match the actual schema that expedia uses
public class AirAvailabilityResults
{
    [System.Xml.Serialization.XmlElement()]
    public AirAvailabilityReply[] AirAvailabilityReply { get; set; }
    [System.Xml.Serialization.XmlAttribute()]
    public int size {get;set;}
    [System.Xml.Serialization.XmlElement()]
    public string cacheKey {get;set;}
    [System.Xml.Serialization.XmlElement()]
    public string cacheLocation {get;set;}
}
public class AirAvailabilityReply
{
    public enum SupplierType
    {
        S
    }
    public enum TripType
    {
        R
    }
    public enum TicketType
    {
        E
    }
    [System.Xml.Serialization.XmlElement()]
    public SupplierType supplierType {get;set;}
    [System.Xml.Serialization.XmlElement()]
    public TripType tripType {get;set;}
    [System.Xml.Serialization.XmlElement()]
    public TicketType ticketType {get;set;}
    public RateInfo RateInfo { get; set; }
    [System.Xml.Serialization.XmlElement()]
    public FlightSegment[] FlightSegment {get;set;}
}
public class RateInfo
{
    public double nativeBaseFare {get;set;}
    public double nativeTotalPrice {get;set;}
    public string nativeCurrencyCode { get; set; }
    public double displayBaseFare {get;set;}
    public double displayTotalPrice {get;set;}
    public string displayCurrencyCode { get; set; }
}
public class FlightSegment
{
    public bool segmentOutgoing {get;set;}
    public string airlineCode {get;set;}
    public string airline {get;set;}
    public int flightNumber {get;set;}
    public string originCityCode {get;set;}
    public string destinationCityCode {get;set;}
    public string departureDateTime {get;set;}
    public string arrivalDateTime { get; set; }
    public string fareClass {get;set;}
    public string equipmentCode {get;set;}
    public int numberOfStops {get;set;}
    public string originCity {get;set;}
    public string originStateProvince {get;set;}
    public string originCountry {get;set;}
    public string destinationCity {get;set;}
    public string desintationStateProvince {get;set;}
    public string destinationCountry { get; set; }
}

API表明RateInfo节点对应于附加的所有兄弟FlightSegment节点。所以你没有RateInfo for 1 FlightSegment