Code Maverick
Code Maverick

Reputation: 20415

Trouble selecting a single node using xPath

I'm simply trying to parse a SOAP Response and pull out the ResponseCode and UnconfirmedReasonCode Elements out of the following XML:

<?xml version="1.0" encoding="utf-8"?>
<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>
    <CoverageResponse xmlns="http://www.iicmva.com/CoverageVerification/">
      <Detail>
        <PolicyInformation>
          <CoverageStatus>
            <ResponseDetails>
              <ResponseCode>CONFIRMED</ResponseCode>
              <UnconfirmedReasonCode/>
            </ResponseDetails>
          </CoverageStatus>
        </PolicyInformation>
      </Detail>
    </CoverageResponse>
  </soap:Body>
</soap:Envelope>

What I've been trying to do is not working:

Dim doc As New XmlDocument
doc.LoadXml(result)

Dim root = doc.DocumentElement.FirstChild.FirstChild
Dim responseDetails = root.SelectSingleNode("descendant::Detail/PolicyInformation/CoverageStatus/ResponseDetails")
Dim responseCode = responseDetails.ChildNodes(0).InnerText
Dim unconfirmedReasonCode = responseDetails.ChildNodes(1).InnerText

Console.WriteLine("Response Details:" & vbCrLf & vbCrLf & responseCode & " " & unconfirmedReasonCode)
Console.ReadLine()

Upvotes: 0

Views: 441

Answers (1)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243449

This is the most FAQ about selecting elements of an XML document with default namespace -- please search for XPath and default namespace. Hint: read about the XmlNamespaceManager class.

A relatively simple and less readable method of selection:

Use:

/*/*/*/*/*/*/*/*[local-name()='ResponseCode']

and use:

/*/*/*/*/*/*/*/*[local-name()='UnconfirmedReasonCode']

XSLT - based verification:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
  <xsl:copy-of select=
  "/*/*/*/*/*/*/*/*[local-name()='ResponseCode']"/>
  <xsl:copy-of select=
  "/*/*/*/*/*/*/*/*[local-name()='UnconfirmedReasonCode']"/>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the provided XML document:

<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>
    <CoverageResponse xmlns="http://www.iicmva.com/CoverageVerification/">
      <Detail>
        <PolicyInformation>
          <CoverageStatus>
            <ResponseDetails>
              <ResponseCode>CONFIRMED</ResponseCode>
              <UnconfirmedReasonCode/>
            </ResponseDetails>
          </CoverageStatus>
        </PolicyInformation>
      </Detail>
    </CoverageResponse>
  </soap:Body>
</soap:Envelope>

The two correctly selected nodes are output:

<ResponseCode xmlns="http://www.iicmva.com/CoverageVerification/" 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">CONFIRMED</ResponseCode>
<UnconfirmedReasonCode xmlns="http://www.iicmva.com/CoverageVerification/" 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" />

Upvotes: 2

Related Questions