Neal Rogers
Neal Rogers

Reputation: 500

How to Parse XML Descendants elements subtree

This XML is a bit different, Each node was originally <dp41:nnnnn (i.e. their Type) and ':' is invalid, so I removed those, leaving this. When parsing it, it returns the entire element and sub tree. So, the question is how to get the elements(nodes) from this xml. The code used returns the entire subtree and specified parent node as one element i.e. from (including)..VehicleValueInfo ...+ all elements within and the close tag VehicleValueInfo /> Wanted is the VehicleValue'node's descendant elements.

XML:

<?xml version="1.0" encoding="UTF-8"?>
    <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
        <s:Body>
            <GetConvergedDataRequestResponse xmlns="http://autoi.trnsn.co.za/types" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
                <ConvergedData i:type="d4p1:ConvergedResults" xmlns:="http://schemas.datacontract.org/2004/07/Trnsn.Auto.Convergence.B2B.BusinessModels">
                    <AccidentHistory i:nil="true"/>
                    <AlertInfo i:nil="true"/>
                    <CloneInfo i:nil="true"/>
                    <DiskDriveInfo>
                        <ResultCode i:nil="true"/>
                        <ResultCodeDescription i:nil="true"/>
                       <AirbagDetails>DRIVER, PASSENGER</AirbagDetails>
                    </DiskDriveInfo>
                    <EnquiryHistory i:nil="true"/>
                        <VehicleValueInfo>
                            <VehicleValue>
                            <ResultCode i:nil="true"/>              
                            <AdjCostPrice>0</AdjCostPrice>
                            <VehicleCode>60007400</VehicleCode>
                        </VehicleValue>
                    </VehicleValueInfo>

Code is;

XNamespace ns = "http://autoi.trnsn.co.za/types";
var xml = XDocument.Parse(InXML);
foreach (XElement element in xml.Descendants("{" + ns + "}VehicleValue"))
{
    Console.WriteLine(element.ToString());
};

The output irrespective of Decendants or elements or a foreach within the first foreach is still the whole tree which is (in it's entirety):

<VehicleValue xmlns="http://autoinsight.transunion.co.za/types">
   <ResultCode i:nil="true" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" />
  <ResultCodeDescription i:nil="true" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" />
      <AdjCostPrice>0</AdjCostPrice>
       ..
       ..
      <VehicleCode>60007400</VehicleCode>
</VehicleValue>

I'm adding The entire Necessary only XML here

<?xml version="1.0" encoding="UTF-8"?>
-<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
   -<s:Body>
      -<GetConvergedDataRequestResponse xmlns="http://autoinsight.trann.co.za/types" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

          -<ConvergedData i:type="ConvergedResults" xmlns:d4p1="http://schemas.datacontract.org/2004/07/Trann.Auto.Convergence.B2B.BusinessModels">
               <AccidentHistory i:nil="true"/>
               <AlertInfo i:nil="true"/> 
               <CloneInfo i:nil="true"/>
               -<DiskDriveInfo>
                    <ResultCode i:nil="true"/>
                    <ResultCodeDescription i:nil="true"/>
                    <AirbagDetails>DRIVER, PASSENGER</AirbagDetails>
                    <Alarm>NO</Alarm>
                </DiskDriveInfo>
                <EnquiryHistory i:nil="true"/>
                <FactoryFittedExtras i:nil="true"/>
                <Finance i:nil="true"/>
                <MileageHistory i:nil="true"/>
                -<VehicleCodeAndDescription>
                    <ResultCode i:nil="true"/>
                    <ResultCodeDescription i:nil="true"/>
                    <VehicleCode>60007400</VehicleCode>
                </VehicleCodeAndDescription>
                <VehicleConfirmationInfo i:nil="true"/>
               -<VehicleValueInfo>
                   -<VehicleValue>
                        <ResultCode i:nil="true"/>
                        <ResultCodeDescription i:nil="true"/>
                        <AdjustCostPrice>0</AdjustCostPrice>
                        <AdjEstCostPrice>0</AdjEstCostPrice>
                        <CostPrice>0</CostPrice>
                        <TradePrice>0</TradePrice>
                        <VehicleCode>60007400</VehicleCode>
                   </VehicleValue>
              </VehicleValueInfo>
              <VesaInfo i:nil="true"/>
         </ConvergedData>

         <ResponseStatus xmlns:d4p1="http://schemas.servicestack.net/types" i:nil="true"/>

      </GetConvergedDataRequestResponse>
   </s:Body>
</s:Envelope>

Upvotes: 0

Views: 527

Answers (3)

jdweng
jdweng

Reputation: 34421

Try this

XNamespace ns = "http://autoi.trnsn.co.za/types";
var xml = XDocument.Parse(InXML);
foreach (XElement element in xml.Descendants(ns + "VehicleValue"))
{
   foreach(XElement ele in element.Elements())
   {
       Console.WriteLine((string)ele);
   }
};​

Upvotes: 1

Sebastian Hofmann
Sebastian Hofmann

Reputation: 1438

If you don't need the namespaces, this could be a solution:

var xml = XDocument.Parse(InXML);
xml.RemoveNamespace();

foreach (XElement element in xml.Descendants("VehicleValue").Elements())
{
    Console.WriteLine(element.ToString());
};

Where RemoveNamespace() is:

public static void RemoveNamespace(this XContainer pContainer)
{
    pContainer.Descendants().Attributes().Where(x => x.IsNamespaceDeclaration).Remove();

    foreach (var element in pContainer.Descendants())
        element.Name = element.Name.LocalName;
}

By the way, it seems the xml is malformed at line 5, position 69. I guess there is a missing namespace prefix declaration...

Upvotes: 0

Marco Salerno
Marco Salerno

Reputation: 5203

You have to use xml.Elements instead of xml.Descendants

var xml = XDocument.Parse(InXML);
foreach (XElement element in xml.Elements("VehicleValue"))
{
    Console.WriteLine(element.ToString());
};

Descendants returns all the tree under the starting element

Elements returns all the direct children of the starting element

Upvotes: 0

Related Questions