1
<row>
    <id>9578</id>
    <processes>
        <process ID="PROCESS A">
            <subprocess ID ="STEP A">
                <val>abcde</val>
            </subprocess>
        </process>
        <process ID="PROCESS B">
            <subprocess ID ="STEP B">
                <val>fghij</val>
            </subprocess>
        </process>
        <process ID="PROCESS C">
            <subprocess ID ="STEP C">
                <val>klmno</val>
            </subprocess>
        </process>
    </processes>
<row>

I am trying to get the data in the val element, but am having trouble. So far, this is what I have:

XmlNodeReader nodereader = new XmlNodeReader(Xdoc);
nodereader.MoveToContent();
var xdoc = XDocument.Load(nodereader); 
var doc_list = xdoc.Descendants("row").Select(x => new
{
    id = x.Element("id").Value,
    ProcessA = x.Element("processes").Elements("process").Single(attr => attr.Attribute("ID").Value == "PROCESS A").Value 
}).ToList();

ProcessA will contain the values of the val element (in this case, abcde). But I keep getting a NullReferenceException. I think I'm almost on the right track, but I still need a little help.

EDIT Thank you everyone for your help but I realize my code works. The issue was just a spelling error due to the id. Instead of

id = x.Element("id").Value,

I accidentally did

id = x.Element("Id").Value,

which resulted in the NullReferenceException for the LINQ. My code to get the val element worked. Moral of the story: sometimes the error might not be where you think it is.

Alya Mohd
  • 13
  • 3
  • Hello, and welcome to Stack Overflow. What object reference are you getting the `NullReferenceException` on? Also, what does `Element("id")` represent? – Jeremy Caney Mar 05 '20 at 08:37
  • Aside, another approach might be to use an [xpath query](https://stackoverflow.com/a/6209890/3025856). – Jeremy Caney Mar 05 '20 at 08:42
  • Can you provide a [mcve]? As you can see from [this fiddle](https://dotnetfiddle.net/BibQbR), your code works fine with the example XML. I can only assume your *real* XML has some of the expected elements or attributes missing for some of the row elements. – Charles Mager Mar 05 '20 at 14:54
  • I tried the xpath query but it didn't work because the xpath is more complicated than the above example. Thank you for you sugesstion! – Alya Mohd Mar 06 '20 at 07:05
  • Thank you for making me double check my code Charles! I checked my code again after your comment and turns out that I had a spelling error on the "id" tag part. – Alya Mohd Mar 06 '20 at 07:07

1 Answers1

4

Is this what you want to do?

var doc = XDocument.Parse(@"<row>
        <id>9578</id>
        <processes>
            <process ID=""PROCESS A"">
                <subprocess ID =""STEP A"">
                    <val>abcde</val>
                </subprocess>
            </process>
            <process ID=""PROCESS B"">
                <subprocess ID =""STEP B"">
                    <val>fghij</val>
                </subprocess>
            </process>
            <process ID=""PROCESS C"">
                <subprocess ID =""STEP C"">
                    <val>klmno</val>
                </subprocess>
            </process>
        </processes>
    </row>");

var doc_list = doc
.Elements("row")
.Elements("processes")
.Elements("process")
.Elements("subprocess")
.Select(x => new{
        Id = x.Attribute("ID").Value,
        ProcessVal = x.Element("val").Value
    })

Alternative using XPath instead:

var doc_list = doc
.XPathSelectElements(@"/row/processes/process/subprocess")
.Select(x => new{
    Id = x.Attribute("ID").Value,
    ProcessVal = x.Element("val").Value
})
mortb
  • 9,361
  • 3
  • 26
  • 44