我有一个非常大的XML文档,它有一些缺少的节点。
良好的XML:
<wd:Job_Family wd:Descriptor="Research/Extension">
<wd:Home_Phone wd:Descriptor="+1 (555) 555-0731">
<wd:ID wd:type="WID">89bfac800b6b41da94e1d1a22b14e66a</wd:ID>
</wd:Home_Phone>
<wd:Home_Address wd:Descriptor="1 Beverly Dr">
错误的XML:
<wd:Job_Family wd:Descriptor="Research/Extension">
***MISSING ***
<wd:Home_Address wd:Descriptor="1 Beverly Dr">
我选择数据的方式是这样的:
List<Employee> employee = new List<Employee>();
try
{
// Get the xml file as stream
StreamReader reader = new StreamReader(outputFileNameAndPath);
// Read the whole contents and return as a string
string xmlString = reader.ReadToEnd();
XDocument doc = XDocument.Parse(xmlString);
XNamespace wd = "urn:com.something.report/Worker_ID_Data_-_Store";
IEnumerable<XElement> worker = doc.Descendants(wd + "Report_Entry");
var query = (from x in doc.Descendants(wd + "Report_Entry")
let jobFamilyAttribute = x.Element(wd + "Job_Family_Group").Attributes(wd + "Descriptor").FirstOrDefault()
select new Employee
{
JobFamily = jobFamilyAttribute.Value
});
employee.AddRange(query);
}
catch (Exception ex)
{
log.Error("An error occurred while trying to parse the XML: " + ex);
}
return employee;
这很有效。我选择了一些额外的节点,但为了简单起见,这就足够了。
现在,当我尝试选择缺少的节点(可能是1000条记录中的1条)时,我得到的Object引用错误未设置为对象的实例。
这是有道理的,因为被选中的节点不在那里。 阅读了很多帖子之后,看起来我应该做一个三元运算符来解释null父级。像这样:
let homePhoneAttribute = x.Element(wd + "Home_Phone") == null ? "" : x.Element(wd + "Home_Phone").Attributes(wd + "Descriptor").FirstOrDefault()
这不是很正确: 无法确定条件表达式的类型,因为&#39; string&#39;之间没有隐式转换。和&#39; System.Xml.Linq.XAttribute&#39;
即使我将它转换为字符串或对象,它也会编译,但是当我添加范围时,我只获得所有记录的第一个值:
let homePhoneAttribute = x.Element(wd + "Home_Phone") == null ? (string)"" : x.Element(wd + "Home_Phone").Attributes(wd + "Descriptor").FirstOrDefault().Value
所以,我啰嗦的问题是,我如何正确地投射和计算空节点,同时仍然能够选择一个让?
我认为它必须是某种DefaultIfEmpty()
投射?
答案 0 :(得分:1)
您可以使用以下表达式:
let homePhoneAttribute = (string)x.Elements(wd + "Home_Phone")
.Attributes(wd + "Descriptor")
.FirstOrDefault()
使用x.Elements()
代替单数形式Element()
,可以避免在找不到元素时出现异常。然后,通过将FirstOrDefault()
返回值转换为string
,如果返回值为null
,则可以避免异常。
<强> dotnetfiddle demo
强>
该演示显示,当homePhoneAttribute
元素缺失时,wd:Home_Phone
变量只包含空字符串。没有例外。
更新:
如果你想要多个属性值(List<string>
)而不仅仅是第一个,你可以修改上面的LINQ,如下所示:
let homePhoneAttribute = x.Elements(wd + "Home_Phone")
.Attributes(wd + "Descriptor")
.Select(o => o.Value)
.ToList()