Sunday Okpokor
Sunday Okpokor

Reputation: 723

Reading xml string with c#

I have the following soap response string:

<EncryptionInfoResponse> <Status>0</Status> <Message></Message> <ServiceID>xxxxxxx</ServiceID> <KeyID>xxxxxxxxx</KeyID> <ContentKey>xxxxxxx</ContentKey> <LicAcqURL><![CDATA[http://sldrm.licensekeyserver.com/core/rightsmanager.asmx]]></LicAcqURL> <LicUIURL></LicUIURL> <CustomXML><![CDATA[<CID>pFRCPIy87oUJtOWis7IYAA==</CID><DRMTYPE>smooth</DRMTYPE>]]></CustomXML> <ContentID>xxxxxxx</ContentID> <PRHeader><![CDATA[<WRMHEADER xmlns="http://schemas.microsoft.com/DRM/2007/03/PlayReadyHeader" version="4.0.0.0"><DATA><PROTECTINFO><KEYLEN>16</KEYLEN><ALGID>AESCTR</ALGID></PROTECTINFO><KID>xvd10JPbxh5rsS27LoCIxQ==</KID><LA_URL>http://sldrm.licensekeyserver.com/core/rightsmanager.asmx</LA_URL><DS_ID>xxxxxx</DS_ID><CUSTOMATTRIBUTES xmlns=""><CID>pFRCPIy87oUJtOWis7IYAA==</CID><DRMTYPE>smooth</DRMTYPE></CUSTOMATTRIBUTES><CHECKSUM>GKaxxISZpMs=</CHECKSUM></DATA></WRMHEADER>]]></PRHeader> </EncryptionInfoResponse>

I want to get the values of "KeyID" and "ContentKey" attributes. I have tried the following below with no success, I got "Sequence contains no elements" error:

string str = Utility.ReadTextFromUrl(ConfigurationManager.AppSettings["SoapUrl"]);
XElement xdoc = XElement.Parse(str);
string result = xdoc.Descendants("EncryptionInfoResponse")
                    .Descendants("KeyID")                       
                    .First()
                    .Value;
return result;

How do I do this?

---- Edit --------------

I figured out that the problem will be the string from the URL which is a PHP script sending request to a soap service. So I wrote a Soap request with C# and was able to get response body of the soap:

using (WebResponse webResponse = webRequest.EndGetResponse(asyncResult))
{
        using (StreamReader rd = new StreamReader(webResponse.GetResponseStream()))
        {
                soapResult = rd.ReadToEnd();
        }
        System.Diagnostics.Debug.WriteLine(soapResult);
        XDocument xDoc = XDocument.Load(new StringReader(soapResult));

      var unwrappedResponse = xDoc.Descendants((XNamespace)"http://schemas.xmlsoap.org/soap/envelope/" + "Body")
                    .First()
                    .FirstNode;
       System.Diagnostics.Debug.WriteLine(unwrappedResponse);

}

But I got stuck here, I have not been able to read the KeyID and ContentKey nodes, this is the response body:

<RequestEncryptionInfoResponse xmlns="http://tempuri.org/">
  <RequestEncryptionInfoResult>&lt;EncryptionInfoResponse&gt;
  &lt;Status&gt;0&lt;/Status&gt;
  &lt;Message&gt;&lt;/Message&gt;
  &lt;ServiceID&gt;xxxx-xxxx-xxx-xxx&lt;/ServiceID&gt;
  &lt;KeyID&gt;xxxx-xxxx-xxx-xxx&lt;/KeyID&gt;
  &lt;ContentKey&gt;KXnH9nzdDbW6kIw11yvY8A==&lt;/ContentKey&gt;
  &lt;LicAcqURL&gt;&lt;![CDATA[http://sldrm.licensekeyserver.com/core/rightsmanager.asmx]]&gt;&lt;/LicAcqURL&gt;
  &lt;LicUIURL&gt;&lt;/LicUIURL&gt;
  &lt;CustomXML&gt;&lt;![CDATA[&lt;CID&gt;RMgchjQPQS+zfHTzsPGSsQ==&lt;/CID&gt;&lt;DRMTYPE&gt;smooth&lt;/DRMTYPE&gt;]]&gt;&lt;/CustomXML&gt;
  &lt;ContentID&gt;861cc844-0f34-2f41-b37c-74f3b0f192b1&lt;/ContentID&gt;
  &lt;PRHeader&gt;&lt;![CDATA[&lt;WRMHEADER xmlns="http://schemas.microsoft.com/DRM/2007/03/PlayReadyHeader" version="4.0.0.0"&gt;&lt;DATA&gt;&lt;PROTECTINFO&gt;&lt;KEYLEN&gt;16&lt;/KEYLEN&gt;&lt;ALGID&gt;AESCTR&lt;/ALGID&gt;&lt;/PROTECTINFO&gt;&lt;KID&gt;ZEjIHDgPQI+zffOw8ZJ0sQ==&lt;/KID&gt;&lt;LA_URL&gt;http://sldrm.licensekeyserver.com/core/rightsmanager.asmx&lt;/LA_URL&gt;&lt;DS_ID&gt;VlR7IdsIJEuRd06Laqs2jw==&lt;/DS_ID&gt;&lt;CUSTOMATTRIBUTES xmlns=""&gt;&lt;CID&gt;RMgchjQPQS+zfHTzsPGSsQ==&lt;/CID&gt;&lt;DRMTYPE&gt;smooth&lt;/DRMTYPE&gt;&lt;/CUSTOMATTRIBUTES&gt;&lt;CHECKSUM&gt;/ytWga+hG9o=&lt;/CHECKSUM&gt;&lt;/DATA&gt;&lt;/WRMHEADER&gt;]]&gt;&lt;/PRHeader&gt;
&lt;/EncryptionInfoResponse&gt;</RequestEncryptionInfoResult>
</RequestEncryptionInfoResponse>

any help?

Upvotes: 0

Views: 355

Answers (2)

Patrick Desjardins
Patrick Desjardins

Reputation: 141013

You do not need to use the first descending. The rest of your code works.

string s = //Your xml here

XElement xdoc = XElement.Parse(s);
string result = xdoc
                    .Descendants("KeyID")                       
                    .First()
                    .Value;
Console.WriteLine(result);

You can also use XPath to get your node:

string s = //Your xml here
XElement xdoc = XElement.Parse(s);
var x = xdoc.CreateNavigator().SelectSingleNode("//KeyID").Value;

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1503859

The problem is that you're using XElement.Parse, so you're parsing the string as an element... so xdoc is already the EncryptionInfoResponse element, which doesn't have any more EncryptionInfoResponse descendants.

Options:

  • Use XDocument.Parse instead, so you end up with a document with an EncryptionInfoResponse element under it
  • Get rid of the Descendants("EncryptionInfoResponse") call, but keep the rest as it is.

Given that the KeyID is a direct child, you could make this simpler using Element(...) instead of Descendants(...).First().

XElement root = XElement.Parse(str);
string result = root.Element("KeyID").Value;

Upvotes: 3

Related Questions