LINQ XML - Select 子元素具有给定值的所有父元素

LINQ XML - Select all parent elements where a child has a given value

从下面的 XML 中,我需要找到有关 FlightSegmentReference ref 等于 BA2759 的所有航班的信息,然后将一些详细信息从父元素传递到 class

 If Len(inFlightNo) > 0 Then
     Dim xdoc As XDocument = XDocument.Parse(rawXML)
     Dim results As IEnumerable(Of Offer) =
         From offer In xdoc.Descendants(myns + "FlightSegmentReference")
             Where offer.Attribute("ref") = inFlightNo
                 Select New Offer With
                 {.FlightRef = offer.Attribute("ref")}
     'Return results
 End If

此示例运行良好...但是我需要获取更多数据以传递到我的 class,例如 TotalAmount SimpleCurrancyPrice 和 OfferItemID

 If Len(inFlightNo) > 0 Then
     Dim xdoc As XDocument = XDocument.Parse(rawXML)
     Dim results As IEnumerable(Of Offer) =
         From offer In xdoc.Descendants(myns + "FlightSegmentReference")
             Where offer.Attribute("ref") = inFlightNo
                 Select New Offer With
                 {.FlightRef = offer.Attribute("ref"),
                  .Price = ????,
                  .OfferItemID = ????
                 }
     'Return results
 End If

在我的 class

中获取 SimpleCurrencyPrice 和填充价格的最佳实践方法是什么

这是XML

<AirlineOffers>
   <TotalOfferQuantity>1156</TotalOfferQuantity>
   <Owner>BA</Owner>
   <AirlineOffer RequestedDateInd="true">
      <OfferID Owner="BA">OFFER1</OfferID>
      <TotalPrice>
         <SimpleCurrencyPrice Code="GBP">129.50</SimpleCurrencyPrice>
      </TotalPrice>
      <PricedOffer>
         <OfferPrice OfferItemID="1">
            <RequestedDate>
               <PriceDetail>
                  <TotalAmount>
                     <SimpleCurrencyPrice Code="GBP">129.50</SimpleCurrencyPrice>
                  </TotalAmount>
                  <BaseAmount Code="GBP">84.00</BaseAmount>
                  <Taxes>
                     <Total Code="GBP">45.50</Total>
                  </Taxes>
               </PriceDetail>
               <Associations>
                  <AssociatedTraveler>
                     <TravelerReferences>SH1</TravelerReferences>
                  </AssociatedTraveler>
               </Associations>
            </RequestedDate>
         </OfferPrice>
         <Associations>
            <ApplicableFlight>
               <FlightSegmentReference ref="BA2759">
                  <ClassOfService>
                     <Code>O</Code>
                     <MarketingName>Euro Traveller</MarketingName>
                  </ClassOfService>
               </FlightSegmentReference>
            </ApplicableFlight>
            <PriceClass>
               <PriceClassReference>Plus</PriceClassReference>
            </PriceClass>
         </Associations>
         <Associations>
            <ApplicableFlight>
               <FlightSegmentReference ref="BA2764">
                  <ClassOfService>
                     <Code>Q</Code>
                     <MarketingName>Euro Traveller</MarketingName>
                  </ClassOfService>
               </FlightSegmentReference>
            </ApplicableFlight>
            <PriceClass>
               <PriceClassReference>Plus</PriceClassReference>
            </PriceClass>
         </Associations>
      </PricedOffer>
   </AirlineOffer>
   <AirlineOffer RequestedDateInd="true">
      <OfferID Owner="BA">OFFER2</OfferID>
      <TotalPrice>
         <SimpleCurrencyPrice Code="GBP">129.50</SimpleCurrencyPrice>
      </TotalPrice>
      <PricedOffer>
         <OfferPrice OfferItemID="1">
            <RequestedDate>
               <PriceDetail>
                  <TotalAmount>
                     <SimpleCurrencyPrice Code="GBP">129.50</SimpleCurrencyPrice>
                  </TotalAmount>
                  <BaseAmount Code="GBP">84.00</BaseAmount>
                  <Taxes>
                     <Total Code="GBP">45.50</Total>
                  </Taxes>
               </PriceDetail>
               <Associations>
                  <AssociatedTraveler>
                     <TravelerReferences>SH1</TravelerReferences>
                  </AssociatedTraveler>
               </Associations>
            </RequestedDate>
         </OfferPrice>
         <Associations>
            <ApplicableFlight>
               <FlightSegmentReference ref="BA2765">
                  <ClassOfService>
                     <Code>O</Code>
                     <MarketingName>Euro Traveller</MarketingName>
                  </ClassOfService>
               </FlightSegmentReference>
            </ApplicableFlight>
            <PriceClass>
               <PriceClassReference>Plus</PriceClassReference>
            </PriceClass>
         </Associations>
         <Associations>
            <ApplicableFlight>
               <FlightSegmentReference ref="BA2764">
                  <ClassOfService>
                     <Code>Q</Code>
                     <MarketingName>Euro Traveller</MarketingName>
                  </ClassOfService>
               </FlightSegmentReference>
            </ApplicableFlight>
            <PriceClass>
               <PriceClassReference>Plus</PriceClassReference>
            </PriceClass>
         </Associations>
      </PricedOffer>
   </AirlineOffer>
</AirlineOffers>

您可以使用 Parent 从 FlightSegmentReference 元素向上导航树:

Dim results As IEnumerable(Of Offer) =
    From ref In xdoc.Descendants(myns + "FlightSegmentReference")
    Where ref.Attribute("ref") = inFlightNo
    Let offer = ref.Parent.Parent.Parent.Parent
    Select New Offer With {
        .FlightRef = ref.Attribute("ref"),
        .Price = CDec(offer.Element(myns + "TotalPrice").Element(myns + "SimpleCurrencyPrice").Value),
        .OfferItemID = offer.Element(myns + "PricedOffer").Element(myns + "OfferPrice").Attribute("OfferItemID")
    }

我喜欢使用 VB.NET 的 XML 语法支持 - 它对我来说似乎更具可读性,尽管您需要 Import 您的命名空间:

Dim results2 As IEnumerable(Of Offer) =
    From e In xdoc...<myns:FlightSegmentReference>
    Where e.@ref = inFlightNo
    Let offer = e.Parent.Parent.Parent.Parent
    Select New Offer() With {
        .FlightRef = e.@ref,
        .Price = CDec(offer.<myns:TotalPrice>.<myns:SimpleCurrencyPrice>.Value),
        .OfferItemID = offer.<myns:PricedOffer>.<myns:OfferPrice>.@OfferItemID
    }

我不是 VB 开发人员,但我认为我要提出的建议很简单,而不是 select FlightSegmentReference 个节点,select PricedOffer 这是包含您需要的所有信息的元素,因此它将是:

Dim results As IEnumerable(Of Offer) =
      From offer In xdoc.Descendants(myns + "PricedOffer")
      Where offer.Descendants(myns +"FlightSegmentReference")
                  .Any(Function(e) e.Attribute("ref").Value = inFlightNo)
      Select New Offer() With {
                          .FlightRef = inFlightNo,
                          .Price = offer.Descendants(myns +"SimpleCurrencyPrice").FirstOrDefault().Value
                          .OfferItemID =offer.Element(myns +"OfferPrice").Attribute("OfferItemID").Value 
}