0

I'm trying to find the number of child elements of where the 'index' attribute matches '2'. I'm expecting an integer value of 2.

My code compiles but generates an error at runtime.

My xml looks like this.

<?xml version="1.0" encoding="utf-8"?>
<dataset>
  <bootfilescomponents>
    <bootfiles index="1">
      <name>Boot Files v2.0</name>
      <file path="File1"></file>
    </bootfiles>
    <bootfiles index="2">
      <name>Boot Files v1.0</name>
      <file path="File1"></file>
      <file path="File2"></file>
    </bootfiles>
    <bootfiles index="3">
      <name>Boot Files v1.3</name>
      <file path="File1"></file>
      <file path="File2"></file>
      <file path="File3"></file>
    </bootfiles>
  </bootfilescomponents>
</dataset>

And here's the code.

xe = XElement.Load("dataset.xml")
Dim NumberOfMatches As Integer = xe.Descendants("bootfiles").Elements("file").Count(Function(x) x.Attribute("index").Value = "2")

Can anyone help me understand where I've gone wrong?

edit: A solution using LINQ

    Dim ct As Integer = 0
    Dim nm As String = "file"
    ct = (From el In xe.Descendants(nm)
            Where el.Parent.Name.LocalName = "bootfiles" AndAlso
            el.Parent.@index = "2"
            Select el).Count
dbasnett
  • 11,334
  • 2
  • 25
  • 33
Darryl
  • 11
  • 4
  • please always post the complete error message – nbk Nov 15 '22 at 14:12
  • You are applying the index condition to "file" elements which do not have an index attribute. Apply it to the boot files: `xe.Descendants("bootfiles").Where(Function(bootFile) bootFile.Attribute("index").Value = "2").Elements("file").Count()` – Olivier Jacot-Descombes Nov 15 '22 at 14:17
  • 'I'm trying to find the number of child (file?) elements of where the 'index' attribute matches '2'. I'm expecting an integer value of 2. Dim ct As Integer = 0 ct = (From el In xe... Where el.Parent.Name.LocalName = "bootfiles" AndAlso el.Parent.@index = "2" Select el).Count – dbasnett Nov 15 '22 at 14:28
  • Thank you @OlivierJacot-Descombes, that makes perfect sense! Though I'm still seeing an issue with the 'Function' part of the code which is throwing a NullReferenceException. – Darryl Nov 15 '22 at 14:28
  • Hi @dbasnett, your code snippet works perfectly, thank you! I wish I understood why my original code was throwing an error but I'm so happy I can get on with this project now. Thank you everyone! – Darryl Nov 15 '22 at 14:38
  • It is working for me with the XML example from above. If e.g. a bootfile is missing the index attribute, then `bootFile.Attribute("index").Value` will throw the Null Ref Exception. Try `bootFile.Attribute("index")?.Value`. Your original code tried to get the index attribute from **file** elements (because the condition was after `.Elements("file")`) instead of from **bootFile** elements. Therefore the Attribute was Nothing and trying to get `.Value` from Nothing throws the exception. – Olivier Jacot-Descombes Nov 15 '22 at 14:40
  • @OlivierJacot-Descombes, great explanation, thank you. If I add the '?' as you showed then the compiler reports that the " '?' cannot be used here". – Darryl Nov 15 '22 at 14:57
  • It works for me. The [Null-Conditional Operator](https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/operators/null-conditional-operators) has been introduced in Visual Basic 2015. It's `?.`, not `?`. – Olivier Jacot-Descombes Nov 15 '22 at 15:24
  • @OlivierJacot-Descombes thank you for confirming that. It looks like I'm facing a compiler issue now then. This does make me wonder why it's throwing the error when each `````` has the "index" attribute then? – Darryl Nov 15 '22 at 15:37
  • `Dim NumberOfMatches As Integer = xe.Descendants("bootfiles").Where(Function(bootFile) bootFile.Attribute("index").Value = "2").Elements("file").Count()` works perfectly for me. Did you remove the Function from `Count`? – Olivier Jacot-Descombes Nov 15 '22 at 15:53
  • I did remove the function from ```Count```. Though I've updated my compiler and now the nullable value works as expected. So I think that clears everything up. Thank you @OlivierJacot-Descombes, I've used your code snippet as it's a little more flexible than using XML literals, and thank you @dbasnett for your snippet too as this is also a valid solution! – Darryl Nov 15 '22 at 16:18
  • @Darryl - '... as it's a little more flexible than using XML literals' How so? – dbasnett Nov 15 '22 at 20:17
  • @dbasnett - the query is part of a function used many times in my code, while my example references an XML element ```"File"``` I need to change this reference using a variable and I could not find a way of doing this using XML literals. Of course, I may be wrong and I'm happy to be corrected. Either way, your code is very clever and I have saved a copy of it for future reference, so please accept my thanks for your help and brilliant example! – Darryl Nov 16 '22 at 15:28
  • @Darryl - I added a string variable, nm, before the ct and changed the first line of the LINQ to From el In xe.Descendants(nm). – dbasnett Nov 16 '22 at 16:06

0 Answers0