Linq to Object / XML where element doesn't exist
var doc3 = XDocument.Load(@"C:\Projects\ScanBandConfigTesting\ScanBandConfigTesting\ScanBandConfigSmall.xml");
var scanBand = new ScanBand()
{
ListOfForms = (from form in doc3.Descendants("form")
select new ScanBandForm()
{
FormTypes = form.Attribute("types").Value,
ScanBandNumber = form.Attribute("number").Value,
ListOfRows = (from row in form.Descendants("row")
select new ScanBandRow()
{
AllowSpaces = row.Element("allowSpaces").Value.ToLower() == "true",
SplitCharacter = row.Element("splitCharacter").Value,
ListOfColumns = (from column in row.Descendants("column")
select new ScanBandColumn()
{
AlwaysKey = column.Element("allwaysKey").IsEmpty ? false : column.Element("allwaysKey").Value.ToLower() == "true",
DataTypeString = column.Element("dataType").IsEmpty ? string.Empty : column.Element("dataType").Value,
MatchingFieldName = column.Element("matchingFieldName").IsEmpty ? string.Empty : column.Element("matchingFieldName").Value,
NonField = column.Element("nonField").IsEmpty ? false : column.Element("nonField").Value.ToLower() == "true",
RegularExpressionString = column.Element("regularExpression").IsEmpty ? string.Empty : column.Element("regularExpression").Value,
}).ToList()
}).ToList()
}).ToList()
};
XML
<scanBand>
<form types="FormName" number="1">
<row>
<allowSpaces>false</allowSpaces>
<splitCharacter> </splitCharacter>
<column>
<matchingFieldName>FirstField</matchingFieldName>
<dataType>CB</dataType>
<regularExpression></regularExpression>
<allwaysKey>false</allwaysKey>
<nonField>false</nonField>
</column>
<column>
<matchingFieldName>SecondField</matchingFieldName>
<dataType>CB</dataType>
<regularExpression></regularExpression>
<allwaysKey>false</allwaysKey>
<nonField>false</nonField>
</column>
<column>
<matchingFieldName>ThirdField</matchingFieldName>
<dataType>CB</dataType>
<regularExpression></regularExpression>
<!--<allwaysKey></allwaysKey>-->
<nonField>true</nonField>
</column>
</row>
</form>
</scanBand>
The goal is to prevent this from exploding when one of the elements in the XML file doesn't exist. I tried to play around with .Any () but was not successful.
I would rather not iterate with foreach and rather stick with w / LINQ
Any help is greatly appreciated
source to share
Don't use a property Value
to get the value of an attribute or element. If node is missing, you will get an exception. When you produce a node (to a string, for example), you will get the default for that type if node is missing. Also you can use the operator ??
to provide your own default for missing row nodes (you will get null by default).
result = (string)column.Element("dataType") ?? String.Empty
Same trick used with boolean values - I get Nullable<bool>
and if it is null
(node is missing) then I assign false
, if it is not null
then node value Invalid property:
ListOfForms =
(from form in doc3.Descendants("form")
select new ScanBandForm() {
FormTypes = (string)form.Attribute("types"),
ScanBandNumber = (string)form.Attribute("number"),
ListOfRows =
(from row in form.Descendants("row")
select new ScanBandRow() {
AllowSpaces = (bool?)row.Element("allowSpaces") ?? false,
SplitCharacter = (string)row.Element("splitCharacter"),
ListOfColumns =
(from column in row.Descendants("column")
select new ScanBandColumn() {
AlwaysKey = (bool?)column.Element("allwaysKey") ?? false,
DataTypeString = (string)column.Element("dataType") ?? String.Empty,
MatchingFieldName = (string)column.Element("matchingFieldName") ?? String.Empty,
NonField = (bool?)column.Element("nonField") ?? false,
RegularExpressionString = (string)column.Element("regularExpression") ?? String.Empty,
}).ToList()
}).ToList()
}).ToList();
source to share