遍历XDocument获取XML元素值时出现对象引用错误求助
VB.NET遍历XDocument时对象引用错误的排查与解决
问题描述
在VB.NET中编写代码遍历XDocument提取XML元素值时,foreach循环内的元素值获取操作触发了对象引用未设置为实例的错误,相关代码如下:
Dim lstrReadXml As String = String.Empty mobjComFun.ReadTextFile(System.Windows.Forms.Application.StartupPath & "\GoFirstBookingXML\GetBookRes.xml", lstrReadXml) Dim lobjXdoc As XDocument = XDocument.Parse(lstrReadXml) Dim lobjNs As New XmlNamespaceManager(lobjXdoc.CreateReader.NameTable) lobjNs.AddNamespace("s", "http://schemas.xmlsoap.org/soap/envelope/") lobjNs.AddNamespace("sc", "http://schemas.navitaire.com/WebServices/ServiceContracts/BookingService") lobjNs.AddNamespace("dc", "http://schemas.navitaire.com/WebServices/DataContracts/Booking") lobjNs.AddNamespace("a", "http://schemas.navitaire.com/WebServices/DataContracts/Common") Dim lstrErrorMsg = String.Empty, lstrQueryStr As String = String.Empty Dim lstrPaxNames As New StringBuilder 'Dim lstrFirstName As String = mobjComFun.GetElementValue(lobjXdoc, "/s:Envelope/s:Body/sc:GetBookingResponse/dc:Booking/dc:Passengers/dc:Passenger/dc:Names", lobjNs, lstrErrorMsg) For Each lobXnode In lobjXdoc.XPathSelectElements("/s:Envelope/s:Body/sc:GetBookingResponse/dc:Booking/dc:Passengers/dc:Passenger", lobjNs) If Not lobXnode Is Nothing Then Dim lobjIEnum As IEnumerable(Of XElement) = From Nam In lobXnode.Elements(lobjNs. & "Names") Select Nam Dim lstrLN As String = lobXnode.Document.Element("LastName").Value lstrPaxNames.Append(lobXnode.XPathSelectElement("/dc:Names", lobjNs).Value) lstrPaxNames.Append(lobXnode.XPathSelectElement("/dc:Names/dc:BookingName/dc:LastName", lobjNs).Value & "/") lstrPaxNames.Append(lobXnode.XPathSelectElement("/dc:Names/dc:BookingName/dc:FirstName", lobjNs).Value & " Y58TWL ") End If Next
错误原因分析
- 语法错误:
lobjNs. & "Names"存在语法错误,无法正确引用命名空间 - 路径错误:
lobXnode.Document.Element("LastName")从整个文档根节点查找元素,而非当前Passenger节点,且未指定命名空间,必然返回Nothing- XPath表达式
"/dc:Names"是绝对路径,从文档根开始查找,而非当前Passenger节点的子元素
- 未做空值判断:直接访问
XPathSelectElement返回结果的Value属性,若元素不存在则触发对象引用错误
修正后的代码
Dim lstrReadXml As String = String.Empty mobjComFun.ReadTextFile(System.Windows.Forms.Application.StartupPath & "\GoFirstBookingXML\GetBookRes.xml", lstrReadXml) Dim lobjXdoc As XDocument = XDocument.Parse(lstrReadXml) Dim lobjNs As New XmlNamespaceManager(lobjXdoc.CreateReader.NameTable) lobjNs.AddNamespace("s", "http://schemas.xmlsoap.org/soap/envelope/") lobjNs.AddNamespace("sc", "http://schemas.navitaire.com/WebServices/ServiceContracts/BookingService") lobjNs.AddNamespace("dc", "http://schemas.navitaire.com/WebServices/DataContracts/Booking") lobjNs.AddNamespace("a", "http://schemas.navitaire.com/WebServices/DataContracts/Common") ' 定义命名空间对象,简化元素查找 Dim dcNs As XNamespace = "http://schemas.navitaire.com/WebServices/DataContracts/Booking" Dim lstrErrorMsg = String.Empty, lstrQueryStr As String = String.Empty Dim lstrPaxNames As New StringBuilder For Each lobXnode In lobjXdoc.XPathSelectElements("/s:Envelope/s:Body/sc:GetBookingResponse/dc:Booking/dc:Passengers/dc:Passenger", lobjNs) If lobXnode IsNot Nothing Then ' 从当前Passenger节点逐级查找子元素,每一步做空值判断 Dim namesElement = lobXnode.Element(dcNs + "Names") If namesElement IsNot Nothing Then Dim bookingNameElement = namesElement.Element(dcNs + "BookingName") If bookingNameElement IsNot Nothing Then Dim lastNameElement = bookingNameElement.Element(dcNs + "LastName") Dim firstNameElement = bookingNameElement.Element(dcNs + "FirstName") ' 确保元素存在再取值 If lastNameElement IsNot Nothing Then lstrPaxNames.Append(lastNameElement.Value & "/") End If If firstNameElement IsNot Nothing Then lstrPaxNames.Append(firstNameElement.Value & " Y58TWL ") End If End If End If ' 备选方案:使用相对路径XPath ' Dim lastName = lobXnode.XPathSelectElement("./dc:Names/dc:BookingName/dc:LastName", lobjNs) ' Dim firstName = lobXnode.XPathSelectElement("./dc:Names/dc:BookingName/dc:FirstName", lobjNs) ' If lastName IsNot Nothing Then lstrPaxNames.Append(lastName.Value & "/") ' If firstName IsNot Nothing Then lstrPaxNames.Append(firstName.Value & " Y58TWL ") End If Next
关键修正点
- 用
XNamespace对象创建带命名空间的元素名,避免语法错误 - 从当前
Passenger节点逐级查找子元素,确保路径正确 - 每一步都判断元素是否为
Nothing,再访问Value属性 - XPath方式改用相对路径
./,从当前节点开始查找而非文档根
内容的提问来源于stack exchange,提问作者Naresh
相关产品推荐
相关产品推荐

