Reputation: 1163
I have an xml file from which I go get ID
s from certain nodes. The nodes have the following structure:
<Bistot ID="1223"/>
<Compressed_Bistot ID="28388"/>
<Compressed_Monoclinic_Bistot ID="28389"/>
...
They are also at different levels in my xml file (it is too big to list it all here).
In order to do this, I use a function that executes a LINQ query:
public String GetItemName(uint id)
{
IEnumerable<String> names = _xmlFile.Descendants()
.Where(x => x.Attributes().Any(a => a.Name.LocalName == "ID") && uint.Parse(x.Attributes().First(a => a.Name.LocalName == "ID").Value) == id)
.Select(t => t.Name.LocalName);
return names.ElementAt(0);
}
In this form, it works well if the id
I provide exists and the names
variable actually has an entry. If it doesn't though, it raises an exception at return names.ElementAt(0);
because there is no elements at index 0
. At this point, in debug mode, if I go check the variable names
, I do see it mentioned that Input string was not in a correct format
, but no error is raised and the function returns the good name
associated to id
.
I have also tried the following form in order to remove the exception that occurs if the LINQ request doesn't find any associated names in the xml file:
public String GetItemName(uint id)
{
IEnumerable<String> names = _xmlFile.Descendants()
.Where(x => x.Attributes().Any(a => a.Name.LocalName == "ID") && uint.Parse(x.Attributes().First(a => a.Name.LocalName == "ID").Value) == id)
.Select(t => t.Name.LocalName);
if (names.Count() != 0) // Error raised here
{
return names.ElementAt(0);
}
else
{
return "";
}
}
This is where my problem occurs, since in this case, when I call names.Count()
, the Input string was not in a correct format
(of type FormatException
) error is raised and my application then does not continue/complete.
I have also tried to call .ToList()
at the end of my LINQ query as I had a warning telling me to do so. But in this case, the Input string was not in a correct format
error is raised inside my LINQ query directly, and not at the names.Count()
call.
I do understand the nature of this error, something is not getting parsed right when I call uint.Parse(x.Attributes().First(a => a.Name.LocalName == "ID").Value)
inside my LINQ query, but I don't understand why for two reasons:
I have manually checked and each values in the ID
attribute in my xml file are real uint
(just numbers, no spaces, etc).
When not using names.Count()
or .ToList()
, while it does mention the error in debug mode when I look at the variable, the name associated to the id
is still found and the function returns it properly.
Why is my uint.Parse(...)
giving me troubles here?
Upvotes: 0
Views: 1582
Reputation: 1502726
The issue is that when you use ElementAt(0)
, it only needs to find the first element - so if there's an ID
element later with an invalid value (which I'm sure there is), you're not going to hit it. When you call Count()
or ToList()
, it iterates over the whole of the query, causing the problem.
As it is, your code is very inefficient though, evaluating multiple times - it would be much better written as:
public String GetItemName(uint id)
{
IEnumerable<String> names = ...; // Query as before
return names.FirstOrDefault() ?? "";
}
I'd also recommend using the explicit conversions provided by LINQ to XML instead of manually calling uint.Parse
, too:
IEnumerable<String> names = _xmlFile.Descendants()
.Where(x => (uint?) x.Attributes()
.Where(a => a.Name.LocalName == "ID")
.FirstOrDefault() == id)
.Select(t => t.Name.LocalName);
Here we're finding the first ID
attribute, converting it to uint?
(giving null
if there's no such attribute) and then comparing that with id
.
Upvotes: 1