1

Let's say I've got a web service response which looks like this:

<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>
    <PMWSGetReportResponse xmlns="http://localhost/PCMilerWS/">
      <PMWSGetReportResult>
        <ReportResponse>
          <Version>25.02</Version>
          <Report>
            <RptType>m</RptType>
            <TripID>011535</TripID>
            <StopNum>1</StopNum>
            <MilesReport>
              <StpLineType>
                <SRStop>
                  <Region>NA</Region>
                  <Address1 />
                  <City>Mill Valley</City>
                  <State>CA</State>
                  <Zip>94941</Zip>
                  <Juris>Marin</Juris>
                  <Lat>37894200</Lat>
                  <Long>-122493488</Long>
                </SRStop>
                <LMiles>0.0</LMiles>
                <TMiles>0.0</TMiles>
                <LCostMile>0.00</LCostMile>
                <TCostMile>0.00</TCostMile>
                <LHours>0:00</LHours>
                <THours>0:00</THours>
                <LTolls>0.00</LTolls>
                <TTolls>0.00</TTolls>
                <LEstghg>0.0</LEstghg>
                <TEstghg>0.0</TEstghg>
              </StpLineType>
              <StpLineType>
                <SRStop>
                  <Region>NA</Region>
                  <Address1 />
                  <City>San Francisco</City>
                  <State>CA</State>
                  <Zip>94109</Zip>
                  <Juris>San Francisco</Juris>
                  <Lat>37790599</Lat>
                  <Long>-122418809</Long>
                  <StopWarning>False</StopWarning>
                </SRStop>
                <LMiles>13.2</LMiles>
                <TMiles>13.2</TMiles>
                <LCostMile>34.33</LCostMile>
                <TCostMile>34.33</TCostMile>
                <LHours>0:17</LHours>
                <THours>0:17</THours>
                <LTolls>12.50</LTolls>
                <TTolls>12.50</TTolls>
                <LEstghg>48.7</LEstghg>
                <TEstghg>48.7</TEstghg>
              </StpLineType>
            </MilesReport>
          </Report>
        </ReportResponse>
      </PMWSGetReportResult>
    </PMWSGetReportResponse>
  </soap:Body>
</soap:Envelope>

I've been trying to use Linq to XML to retrieve, say, the list of all StpLineType nodes. I've tried doing so with something like:

XDocument xdoc = XDocument.Load(new StringReader(soapResponse));
var results = xdoc.Descendants("StpLineType");

But nothing is returned. I can see that the document is loaded into xdoc, but I can't seem to correctly query it. FWIW, I've also tried:

XDocument xdoc = XDocument.Load(new StringReader(soapResponse));
XNamespace ns = "soap";
var results = xdoc.Descendants(ns + "StpLineType");

Just in case the namespace was causing the problem - no luck.

What am I missing?

Michael
  • 4,010
  • 4
  • 28
  • 49

3 Answers3

0

Try

XDocument xdoc = XDocument.Load(new StringReader(soapResponse));
XNamespace ns = "http://localhost/PCMilerWS/";
var results = xdoc.Descendants(ns + "StpLineType");
Bala R
  • 107,317
  • 23
  • 199
  • 210
  • results still contains no matches {System.Xml.Linq.XContainer.GetDescendants} name: null self: false System.Collections.Generic.IEnumerator.Current: null System.Collections.IEnumerator.Current: null results.First() A first chance exception of type 'System.InvalidOperationException' occurred in System.Core.dll – Michael Oct 01 '11 at 20:37
  • I just tried my edited snipped in linqpad and it works! See http://i.imgur.com/Md4Pl.png – Bala R Oct 01 '11 at 20:37
0

You should register the "soap" namespace using the XmlNamespaceManager.

Check out this post:

XDocument containing namespaces

Community
  • 1
  • 1
Anas Karkoukli
  • 1,342
  • 8
  • 13
  • That alone won't help - the nodes below are all contained in a separate, different XML namespace.... – marc_s Oct 01 '11 at 20:39
0

You're ignoring the two XML namespaces on this document!

  • The root level and the <body> tag are in the soap namespace
  • the rest of the document is in the "default" namespace (without prefix) defined on the <PMWSGetReportResponse> element

If you take that into account - things begin to work just fine!

XDocument xdoc = XDocument.Load(new StringReader(soapResponse));

XNamespace soap = "http://schemas.xmlsoap.org/soap/envelope/";
XNamespace ns = "http://localhost/PCMilerWS/";

var results = xdoc.Root.Element(soap + "Body").Descendants(ns + "StpLineType");

But the main question really is: why on earth are you manually parsing a SOAP response?? .....

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • This works, thanks, and I'll be accepting it as soon as SO overflow lets me. But to your question, as opposed to manually parsing it, are you asking why I'm not deserializing it into strongly typed objects? – Michael Oct 01 '11 at 20:44
  • @Michael: yes, exactly! Why don't you have a SOAP client-side proxy that gives you nice, properly deserialized data back - instead of having to manually go through this messy parsing... – marc_s Oct 01 '11 at 20:45
  • it's a fair question. The short answer is the project requires a-lot of run-time "flexibility". Thanks for the answer! – Michael Oct 01 '11 at 21:03