XML 对 Linq 的响应
XML Response to Linq
我的 XML 回复如下所示:
"<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<HotelAvailResponse xmlns="http://www.juniper.es/webservice/2007/">
<AvailabilityRS Url="http://xml.bookingengine.es"
TimeStamp="20130327T14:38:54.6916528+01:00"
IntCode="lCf65bPrG+x7VDLB0IquVNQgKloRA9+HOuhfHMj0BcE=">
<Results>
<HotelResult Code="7b0LYEzfsd0HH90sd" JPCode="JP003600" DestinationZone="39303" JPDCode="JPD000014">
<HotelInfo>
<Name>Hotel Test</Name>
<Description>A spacious, quiet, light and bright hotel, with a garden and fabulous views across the city.</Description>
<Images>
<Image>http://www.bookingengine.es/images/upload_p/hoteltest.jpeg</Image>
</Images>
<HotelCategory>1 1/2 Stars</HotelCategory>
<HotelType Type="SKI">Snow</HotelType>
<Address>c/tap</Address>
</HotelInfo>
<HotelOptions>
<HotelOption RatePlanCode="dcFZbKty1cJGKeRtgxIDGUZAprp1mua8ySl4iVIZ7NVKBF/PGk8lhZlN7Hcszjs2RwUR2Dxsrv5l0cZDORKz6frEmPdibqOyV2Jg4Dxz8/bF5gqPyQR8+z1LEu8LCVlS" Status="OK">
<Board Type="AD">Bed&Breakfast</Board>
<Prices>
<Price Type="S" Currency="USD">
<TotalFixAmounts Gross="353.65" Nett="353.65">
<Service Amount="321.5"/>
<ServiceTaxes Included="true" Amount="32.15"/>
<Commissions Included="true" Amount="0"/>
<HandlingFees Included="true" Amount="0"/>
<Discount Amount="-0"/>
</TotalFixAmounts>
</Price>
</Prices>
<HotelRooms>
<HotelRoom Units="1" Source="1" AvailRooms="12">
<Name>Double Room</Name>
<RoomCategory Type="DBL">Double Standard</RoomCategory>
</HotelRoom>
<HotelRoom Units="1" Source="2" AvailRooms="45">
<Name>Single</Name>
<RoomCategory Type="SGL">Single Standard</RoomCategory>
</HotelRoom>
</HotelRooms>
</HotelOption>
<HotelOption RatePlanCode="dcFZbKty1cJGKeRtgxIDGUZAprp1mua8ySl4iVIZ7NVKBF/PGk8lhZlN7Hcszjs2RwUR2Dxsrv5l0cZDORKz6frEmPdibqOyV2Jg4Dxz8/bmoX041DU9+3D3nHCEB/6vYKbVtJR2qaHwW9VnnWl/KA==" Status="OK">
<Board Type="AD">Bed&Breakfast</Board>
<Prices>
<Price Type="S" Currency="USD">
<TotalFixAmounts Gross="353.65" Nett="353.65">
<Service Amount="321.5"/>
<ServiceTaxes Included="true" Amount="32.15"/>
<Commissions Included="true" Amount="0"/>
<HandlingFees Included="true" Amount="0"/>
<Discount Amount="-0"/>
</TotalFixAmounts>
</Price>
</Prices>
<HotelRooms>
<HotelRoom Units="1" Source="1" AvailRooms="12">
<Name>Double Room</Name>
<RoomCategory Type="DBL">Double Standard</RoomCategory>
</HotelRoom>
<HotelRoom Units="1" Source="2" AvailRooms="11">
<Name>Double Room</Name>
<RoomCategory Type="DBL">Double Standard</RoomCategory>
</HotelRoom>
</HotelRooms>
<AdditionalElements>
<HotelOffers>
<HotelOffer>
<Name>Basic Discount 10%</Name>
</HotelOffer>
</HotelOffers>
</AdditionalElements>
</HotelOption>
</HotelOptions>
</HotelResult>
</Results>
</AvailabilityRS>
</HotelAvailResponse>
</soap:Body>
</soap:Envelope>"
我有这个 Linq 的响应如下:
XNamespace ns = "http://schemas.xmlsoap.org/soap/envelope/";
var hotels = (from hotelData in data.Descendants(ns + "Envelope").Descendants(ns + "Body").Descendants("HotelAvailResponse").Descendants("HotelAvailResult").Descendants("Results").Descendants("HotelResult")
select new Hotel
{
Code = hotelData.Attribute("Code").Value,
JpCode =
hotelData.Attributes().Any(x => x.Name == "JPCode")
? hotelData.Attribute("JPCode").Value
: "",
DestinationZone =
hotelData.Attribute("DestinationZone") != null
? hotelData.Attribute("DestinationZone").Value
: string.Empty,
JpdCode = hotelData.Attribute("JPDCode").Value,
//HotelName = Convert.ToString(hotelData.Element("Item").Value),
//Rating = Convert.ToInt32(hotelData.Element("StarRating").Value),
HotelInfo = (from hi in hotelData.Descendants("HotelInfo")
select new HotelInfo
{
Name = hi.Element("Name").Value,
Description = hi.Element("Description").Value,
Image = (from img in hi.Descendants("Images") select new Imagez { Images = img.Element("Image").Value }).ToList(),
HotelCategory = hi.Element("Name").Value,
HotelType = hi.Element("Description").Value,
Address = hi.Element("Description").Value,
}
).ToList(),
HotelOptions = (from ho in hotelData.Descendants("HotelOptions")
select new HotelOptions()
{
HotelOption = ho.Element("HotelOption").Attribute("RatePlanCode").Value,
Board = ho.Element("Board").Attribute("Type").Value,
Prices = (from pr in ho.Descendants("Prices") select new Prices() { Price = pr.Element("Price").Value,
TotalFixAmounts = (from tfa in pr.Descendants("TotalFixAmounts") select new TotalFixAmounts()
{ Service = tfa.Element("Service").Attribute("Amount").Value,
ServiceTaxes = tfa.Element("ServiceTaxes").Attribute("Included").Value,
AmountServiceTaxes = tfa.Element("ServiceTaxes").Attribute("Amount").Value,
Commissions = tfa.Element("Commissions").Attribute("Included").Value,
AmountCommissions = tfa.Element("Commissions").Attribute("Amount").Value,
HandlingFees = tfa.Element("HandlingFees").Attribute("Included").Value,
AmountHandlingFees = tfa.Element("HandlingFees").Attribute("Amount").Value,
Discount = tfa.Element("Amount").Attribute("Included").Value,
}).ToList(),
}).ToList(),
}).ToList(),
}).ToList();
return hotels;
我没有收到任何错误,也没有任何异常,但返回的酒店数量为 0。
我是 Linq 的初学者。
任何帮助将不胜感激,并且已经连续 7 个小时了,我正在寻求帮助并努力完成它。现在感觉死路一条了
提前致谢。
您发布的代码存在一些问题。
第一个问题是代码没有考虑分配给 <HotelResult>
的命名空间。命名空间是 http://wwww.juniper.es/webservice/2007/,继承自 <HotelAvailResponse>
元素。您可以将命名空间视为 xmlns
属性:
<HotelAvailResponse xmlns="http://www.juniper.es/webservice/2007/">
这就是您的 LINQ 查询未返回任何内容的原因 - 它正在寻找具有 XML 命名空间 http://schemas.xmlsoap.org/soap/envelope 的 <HotelAvailResponse>
,并且该节点不存在,因此您得到一个空集合。每次调用 Descendants
或 Element
时,都需要包含名称空间(即 ns + "ElementName"
)。
在代码实际运行之前,第二个问题并不明显,但下面的语句
HotelOptions = (from ho in hotelData.Descendants(ns + "HotelOption")
将导致 <HotelOption>
和 <Board>
只出现一次(即 1 的列表)而不是两次。 <price>
信息和 <TotalFixAmounts>
正确填充 - 我不完全确定为什么,但这可能与 <TotalFixAmounts>
的嵌套列表有关。这很容易通过将 select 更改为 <HotelOption>
来解决,如下所示:
HotelOption = (from ho in hotelData.Descendants("HotelOption")
现在 ho
将是 <HotelOption>
个节点及其子节点的集合,两者都将被处理,嵌套列表也将被处理。
接下来,您的 LINQ 语句有几个问题会抛出空引用异常(假设名称空间问题已得到纠正)。它们是:
Board = ho.Element("Board").Attribute("Type").Value;
ho
是所有 <HotelOptions>
节点及其子节点的集合 - 但 <Board>
是 <HotelOption>
的子节点,它本身是 <HotelOptions>
。使用 XML 时,请记住它本质上是分层的 - .Element(elementName)
将访问具有该名称的 first 元素是一个子元素(不是孙子元素或更远的子元素) ) 的父元素。一个相当简单的解决方案是将 <HotelOption>
添加到语句中:
Board = ho.Element(ns + "HotelOption").Element(ns + "Board").Attribute("Type").Value;
此处出现类似问题:
TotalFixAmounts = (from tfa in pr.Descendants("Prices") select new
pr
是 <Prices>
个节点的集合,但 select
语句中引用的元素是 <Price>
的子元素,而不是 <Prices>
。 Element(elementName)
会得到父元素的第一个子节点,而<Prices>
除了<Price>
.
没有其他子节点
最后,没有 <Amount>
元素是 <TotalFixAmounts>
的子元素,所以下面这行也会抛出空引用异常:
Discount = tfa.Element("Amount").Attribute("Included").Value;
代替您使用的两个三元运算符,我建议使用 (string)
- 显式转换将安全地处理缺失的元素或属性。如果缺少元素或属性,代码不会失败,它只是没有值 属性.
因此,将所有这些放在一起你会得到:
XNamespace ns = "http://www.juniper.es/webservice/2007/";
var hotels = (from hotelData in data.Root.Descendants(ns + "HotelResult")
select new Hotel
{
Code = (string)hotelData.Attribute("Code"),
JpCode = (string)hotelData.Attribute("JPCode"),
DestinationZone = (string)hotelData.Attribute("DestinationZone"),
JpdCode = (string)hotelData.Attribute("JPDCode"),
HotelInfo = (from hi in hotelData.Descendants(ns + "HotelInfo")
select new HotelInfo
{
Name = (string)hi.Element("Name"),
Description = (string)hi.Element(ns + "Description"),
Image = (from img in hi.Descendants(ns + "Images")
select new Imagez
{
Images = (string)img.Element(ns + "Image")
}).ToList(),
HotelCategory = (string)hi.Element(ns + "Name"),
HotelType = (string)hi.Element(ns + "Description"),
Address = (string)hi.Element(ns + "Description"),
}).ToList(),
HotelOptions = (from ho in hotelData.Descendants(ns + "HotelOption")
select new HotelOptions
{
HotelOption = ho.Attribute("RatePlanCode").Value,
Board = ho.Element(ns + "Board").Attribute("Type").Value,
Prices = (from pr in ho.Descendants(ns + "Prices")
select new Price
{
Price = (string)pr.Element(ns + "Price"),
TotalFixAmounts = (from tfa in pr.Descendants(ns + "Price").Descendants(ns + "TotalFixAmounts")
select new TotalFixAmounts
{
Service = tfa.Element(ns + "Service").Attribute("Amount").Value,
ServiceTaxes = tfa.Element(ns + "ServiceTaxes").Attribute("Included").Value,
AmountServiceTaxes = tfa.Element(ns + "ServiceTaxes").Attribute("Amount").Value,
Commissions = tfa.Element(ns + "Commissions").Attribute("Included").Value,
AmountCommissions = tfa.Element(ns + "Commissions").Attribute("Amount").Value,
HandlingFees = tfa.Element(ns + "HandlingFees").Attribute("Included").Value,
AmountHandlingFees = tfa.Element(ns + "HandlingFees").Attribute("Amount").Value
}).ToList(),
}).ToList(),
}).ToList(),
}).ToList();
请注意,每个对 Descendants
或 Element
的引用都包含命名空间 ns
。
我的 XML 回复如下所示:
"<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<HotelAvailResponse xmlns="http://www.juniper.es/webservice/2007/">
<AvailabilityRS Url="http://xml.bookingengine.es"
TimeStamp="20130327T14:38:54.6916528+01:00"
IntCode="lCf65bPrG+x7VDLB0IquVNQgKloRA9+HOuhfHMj0BcE=">
<Results>
<HotelResult Code="7b0LYEzfsd0HH90sd" JPCode="JP003600" DestinationZone="39303" JPDCode="JPD000014">
<HotelInfo>
<Name>Hotel Test</Name>
<Description>A spacious, quiet, light and bright hotel, with a garden and fabulous views across the city.</Description>
<Images>
<Image>http://www.bookingengine.es/images/upload_p/hoteltest.jpeg</Image>
</Images>
<HotelCategory>1 1/2 Stars</HotelCategory>
<HotelType Type="SKI">Snow</HotelType>
<Address>c/tap</Address>
</HotelInfo>
<HotelOptions>
<HotelOption RatePlanCode="dcFZbKty1cJGKeRtgxIDGUZAprp1mua8ySl4iVIZ7NVKBF/PGk8lhZlN7Hcszjs2RwUR2Dxsrv5l0cZDORKz6frEmPdibqOyV2Jg4Dxz8/bF5gqPyQR8+z1LEu8LCVlS" Status="OK">
<Board Type="AD">Bed&Breakfast</Board>
<Prices>
<Price Type="S" Currency="USD">
<TotalFixAmounts Gross="353.65" Nett="353.65">
<Service Amount="321.5"/>
<ServiceTaxes Included="true" Amount="32.15"/>
<Commissions Included="true" Amount="0"/>
<HandlingFees Included="true" Amount="0"/>
<Discount Amount="-0"/>
</TotalFixAmounts>
</Price>
</Prices>
<HotelRooms>
<HotelRoom Units="1" Source="1" AvailRooms="12">
<Name>Double Room</Name>
<RoomCategory Type="DBL">Double Standard</RoomCategory>
</HotelRoom>
<HotelRoom Units="1" Source="2" AvailRooms="45">
<Name>Single</Name>
<RoomCategory Type="SGL">Single Standard</RoomCategory>
</HotelRoom>
</HotelRooms>
</HotelOption>
<HotelOption RatePlanCode="dcFZbKty1cJGKeRtgxIDGUZAprp1mua8ySl4iVIZ7NVKBF/PGk8lhZlN7Hcszjs2RwUR2Dxsrv5l0cZDORKz6frEmPdibqOyV2Jg4Dxz8/bmoX041DU9+3D3nHCEB/6vYKbVtJR2qaHwW9VnnWl/KA==" Status="OK">
<Board Type="AD">Bed&Breakfast</Board>
<Prices>
<Price Type="S" Currency="USD">
<TotalFixAmounts Gross="353.65" Nett="353.65">
<Service Amount="321.5"/>
<ServiceTaxes Included="true" Amount="32.15"/>
<Commissions Included="true" Amount="0"/>
<HandlingFees Included="true" Amount="0"/>
<Discount Amount="-0"/>
</TotalFixAmounts>
</Price>
</Prices>
<HotelRooms>
<HotelRoom Units="1" Source="1" AvailRooms="12">
<Name>Double Room</Name>
<RoomCategory Type="DBL">Double Standard</RoomCategory>
</HotelRoom>
<HotelRoom Units="1" Source="2" AvailRooms="11">
<Name>Double Room</Name>
<RoomCategory Type="DBL">Double Standard</RoomCategory>
</HotelRoom>
</HotelRooms>
<AdditionalElements>
<HotelOffers>
<HotelOffer>
<Name>Basic Discount 10%</Name>
</HotelOffer>
</HotelOffers>
</AdditionalElements>
</HotelOption>
</HotelOptions>
</HotelResult>
</Results>
</AvailabilityRS>
</HotelAvailResponse>
</soap:Body>
</soap:Envelope>"
我有这个 Linq 的响应如下:
XNamespace ns = "http://schemas.xmlsoap.org/soap/envelope/";
var hotels = (from hotelData in data.Descendants(ns + "Envelope").Descendants(ns + "Body").Descendants("HotelAvailResponse").Descendants("HotelAvailResult").Descendants("Results").Descendants("HotelResult")
select new Hotel
{
Code = hotelData.Attribute("Code").Value,
JpCode =
hotelData.Attributes().Any(x => x.Name == "JPCode")
? hotelData.Attribute("JPCode").Value
: "",
DestinationZone =
hotelData.Attribute("DestinationZone") != null
? hotelData.Attribute("DestinationZone").Value
: string.Empty,
JpdCode = hotelData.Attribute("JPDCode").Value,
//HotelName = Convert.ToString(hotelData.Element("Item").Value),
//Rating = Convert.ToInt32(hotelData.Element("StarRating").Value),
HotelInfo = (from hi in hotelData.Descendants("HotelInfo")
select new HotelInfo
{
Name = hi.Element("Name").Value,
Description = hi.Element("Description").Value,
Image = (from img in hi.Descendants("Images") select new Imagez { Images = img.Element("Image").Value }).ToList(),
HotelCategory = hi.Element("Name").Value,
HotelType = hi.Element("Description").Value,
Address = hi.Element("Description").Value,
}
).ToList(),
HotelOptions = (from ho in hotelData.Descendants("HotelOptions")
select new HotelOptions()
{
HotelOption = ho.Element("HotelOption").Attribute("RatePlanCode").Value,
Board = ho.Element("Board").Attribute("Type").Value,
Prices = (from pr in ho.Descendants("Prices") select new Prices() { Price = pr.Element("Price").Value,
TotalFixAmounts = (from tfa in pr.Descendants("TotalFixAmounts") select new TotalFixAmounts()
{ Service = tfa.Element("Service").Attribute("Amount").Value,
ServiceTaxes = tfa.Element("ServiceTaxes").Attribute("Included").Value,
AmountServiceTaxes = tfa.Element("ServiceTaxes").Attribute("Amount").Value,
Commissions = tfa.Element("Commissions").Attribute("Included").Value,
AmountCommissions = tfa.Element("Commissions").Attribute("Amount").Value,
HandlingFees = tfa.Element("HandlingFees").Attribute("Included").Value,
AmountHandlingFees = tfa.Element("HandlingFees").Attribute("Amount").Value,
Discount = tfa.Element("Amount").Attribute("Included").Value,
}).ToList(),
}).ToList(),
}).ToList(),
}).ToList();
return hotels;
我没有收到任何错误,也没有任何异常,但返回的酒店数量为 0。 我是 Linq 的初学者。 任何帮助将不胜感激,并且已经连续 7 个小时了,我正在寻求帮助并努力完成它。现在感觉死路一条了
提前致谢。
您发布的代码存在一些问题。
第一个问题是代码没有考虑分配给 <HotelResult>
的命名空间。命名空间是 http://wwww.juniper.es/webservice/2007/,继承自 <HotelAvailResponse>
元素。您可以将命名空间视为 xmlns
属性:
<HotelAvailResponse xmlns="http://www.juniper.es/webservice/2007/">
这就是您的 LINQ 查询未返回任何内容的原因 - 它正在寻找具有 XML 命名空间 http://schemas.xmlsoap.org/soap/envelope 的 <HotelAvailResponse>
,并且该节点不存在,因此您得到一个空集合。每次调用 Descendants
或 Element
时,都需要包含名称空间(即 ns + "ElementName"
)。
在代码实际运行之前,第二个问题并不明显,但下面的语句
HotelOptions = (from ho in hotelData.Descendants(ns + "HotelOption")
将导致 <HotelOption>
和 <Board>
只出现一次(即 1 的列表)而不是两次。 <price>
信息和 <TotalFixAmounts>
正确填充 - 我不完全确定为什么,但这可能与 <TotalFixAmounts>
的嵌套列表有关。这很容易通过将 select 更改为 <HotelOption>
来解决,如下所示:
HotelOption = (from ho in hotelData.Descendants("HotelOption")
现在 ho
将是 <HotelOption>
个节点及其子节点的集合,两者都将被处理,嵌套列表也将被处理。
接下来,您的 LINQ 语句有几个问题会抛出空引用异常(假设名称空间问题已得到纠正)。它们是:
Board = ho.Element("Board").Attribute("Type").Value;
ho
是所有 <HotelOptions>
节点及其子节点的集合 - 但 <Board>
是 <HotelOption>
的子节点,它本身是 <HotelOptions>
。使用 XML 时,请记住它本质上是分层的 - .Element(elementName)
将访问具有该名称的 first 元素是一个子元素(不是孙子元素或更远的子元素) ) 的父元素。一个相当简单的解决方案是将 <HotelOption>
添加到语句中:
Board = ho.Element(ns + "HotelOption").Element(ns + "Board").Attribute("Type").Value;
此处出现类似问题:
TotalFixAmounts = (from tfa in pr.Descendants("Prices") select new
pr
是 <Prices>
个节点的集合,但 select
语句中引用的元素是 <Price>
的子元素,而不是 <Prices>
。 Element(elementName)
会得到父元素的第一个子节点,而<Prices>
除了<Price>
.
最后,没有 <Amount>
元素是 <TotalFixAmounts>
的子元素,所以下面这行也会抛出空引用异常:
Discount = tfa.Element("Amount").Attribute("Included").Value;
代替您使用的两个三元运算符,我建议使用 (string)
- 显式转换将安全地处理缺失的元素或属性。如果缺少元素或属性,代码不会失败,它只是没有值 属性.
因此,将所有这些放在一起你会得到:
XNamespace ns = "http://www.juniper.es/webservice/2007/";
var hotels = (from hotelData in data.Root.Descendants(ns + "HotelResult")
select new Hotel
{
Code = (string)hotelData.Attribute("Code"),
JpCode = (string)hotelData.Attribute("JPCode"),
DestinationZone = (string)hotelData.Attribute("DestinationZone"),
JpdCode = (string)hotelData.Attribute("JPDCode"),
HotelInfo = (from hi in hotelData.Descendants(ns + "HotelInfo")
select new HotelInfo
{
Name = (string)hi.Element("Name"),
Description = (string)hi.Element(ns + "Description"),
Image = (from img in hi.Descendants(ns + "Images")
select new Imagez
{
Images = (string)img.Element(ns + "Image")
}).ToList(),
HotelCategory = (string)hi.Element(ns + "Name"),
HotelType = (string)hi.Element(ns + "Description"),
Address = (string)hi.Element(ns + "Description"),
}).ToList(),
HotelOptions = (from ho in hotelData.Descendants(ns + "HotelOption")
select new HotelOptions
{
HotelOption = ho.Attribute("RatePlanCode").Value,
Board = ho.Element(ns + "Board").Attribute("Type").Value,
Prices = (from pr in ho.Descendants(ns + "Prices")
select new Price
{
Price = (string)pr.Element(ns + "Price"),
TotalFixAmounts = (from tfa in pr.Descendants(ns + "Price").Descendants(ns + "TotalFixAmounts")
select new TotalFixAmounts
{
Service = tfa.Element(ns + "Service").Attribute("Amount").Value,
ServiceTaxes = tfa.Element(ns + "ServiceTaxes").Attribute("Included").Value,
AmountServiceTaxes = tfa.Element(ns + "ServiceTaxes").Attribute("Amount").Value,
Commissions = tfa.Element(ns + "Commissions").Attribute("Included").Value,
AmountCommissions = tfa.Element(ns + "Commissions").Attribute("Amount").Value,
HandlingFees = tfa.Element(ns + "HandlingFees").Attribute("Included").Value,
AmountHandlingFees = tfa.Element(ns + "HandlingFees").Attribute("Amount").Value
}).ToList(),
}).ToList(),
}).ToList(),
}).ToList();
请注意,每个对 Descendants
或 Element
的引用都包含命名空间 ns
。