Get children of XML using LINQ and XDocument

Viewed 248

I can parse an XML and get this specific chunk off it like so:

var document = XDocument.Parse(xml);

            var envelopeStatusElement = document.Root
                .Elements()
                .SingleOrDefault(e => e.Name.LocalName == "EnvelopeStatus");

envelopeStatusElement:

<EnvelopeStatus xmlns="http://www.docusign.net/API/3.0">
  <RecipientStatuses>
    <RecipientStatus>
      <Type>Signer</Type>
      <Email>test@dev.com</Email>
      <Status>Sent</Status>
      <RecipientIPAddress />
      
      <CustomFields>
        <CustomField>123</CustomField>
      </CustomFields>
      
    </RecipientStatus>
  </RecipientStatuses>
  <EnvelopeID>123456789</EnvelopeID>
  <CustomFields>
    <CustomField>
      <Name>templateUsageRestriction</Name>
      <Show>False</Show>
      <Required>False</Required>
      <Value>allOptions</Value>
    </CustomField>
    
    <CustomField>
      <Name>mailingListId</Name>
      <Show>False</Show>
      <Required>False</Required>
      <Value>987</Value>
    </CustomField>
    
  </CustomFields>
</EnvelopeStatus>

Im having a real hard time getting the value of the CustomField inside RecipientStatus(123) and also the value of CustomField inside CustomFields but with Name mailingListId(987).

Ive gotten close trying what Ive got in this pic but theres gotta be a more effective way to do this, apologies if its super obvious still very new to LINQ and C#

1 Answers
<EnvelopeStatus xmlns="http://www.docusign.net/API/3.0">

Your root element has a default namespace so every element has to be qualified with it, unless you override it which you never do. I see your sample code goes through contortions trying to circumvent the namespace. Do not do that, it makes your code slow and inaccurate.

Fortunately, .NET comes with an XNamespace class that overrides string assignment to create namespace instances, and overrides string concatenation to create namespace-qualified XName instances.

You can use them to get the value of the first element inside CustomFields inside the first RecipientStatus with something like:

XNamespace ns = "http://www.docusign.net/API/3.0";
var firstStatusFirstCustomFieldValue = document.Element(ns + "EnvelopeStatus")
    .Element(ns + "RecipientStatuses")
    .Elements(ns + "RecipientStatus")
    .First()
    .Element(ns + "CustomFields")
    .Elements(ns + "CustomField")
    .First().Value;

You will have to modify the code if you want to get something other than the first RecipientStatus or CustomField.

Avoid the temptation to replace all this code with something using Descendants; doing that will also make your code slow and inaccurate.

Related