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>
像上文提到的那样使用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