如何用LINQ查询XML父元素属性并匹配文件扩展名
XML与LINQ查询问题
一、需求:根据文件扩展名提取TargetId
现有如下XML结构:
<?xml version="1.0" encoding="UTF-8"?> <Targets> <FileType TargetId="image"> <FileExtension>jpg</FileExtension> <FileExtension>jpeg</FileExtension> <FileExtension>tif</FileExtension> <FileExtension>tiff</FileExtension> <FileExtension>gif</FileExtension> <FileExtension>png</FileExtension> </FileType> </Targets>
需要根据指定的文件扩展名(如jpeg),查找并提取对应的TargetId。首次使用包含重复FileExtension元素的结构,始终无法匹配到目标。
二、过往测试中的属性访问异常
此前使用如下XML结构的测试代码可正常查询元素:
<body> <Customers> <Client TestAttr="testing-123"> <Firstname>someguy</Firstname> <LastName>some other last name again</LastName> <PhoneNumber>12345634543</PhoneNumber> <City>some other town</City> <State>some other state</State> </Client> </Customers> </body>
查询代码:
IEnumerable<XElement> someClients = from el in doc.Elements("Customers").Elements("Client") where (string)el.Element("PhoneNumber") == phoneNumberToFind select el;
能正常找到目标元素,也可获取同一Client下的其他元素:
Console.WriteLine("Found client named '{0}'", (string)el.Element("LastName").Value );
但访问元素属性时,所有尝试均触发NullReferenceException:
An unhandled exception of type 'System.NullReferenceException' occurred in ......dll: 'Object reference not set to an instance of an object.'
尝试的代码包括:
string fTestAttr1 = (string)el.Element("Client").Value; string fTestAttr2 = (string)el.Element("Client").Attribute("TestAttr"); string fTestAttr3 = (string)el.Element("Client").Attribute("TestAttr").Value; string fTestAttr4 = (string)el.Element("Client").FirstAttribute.Value; string fTestAttr4 = (string)el.Element("Client").FirstAttribute.Value);
调试中可见el是XElement类型,但不清楚如何正确访问属性,也不明白为何会出现空引用异常。
解决方案
1. 解决属性访问的空引用问题
你之前的代码错误在于:el本身就是Client元素,不需要再调用el.Element("Client")——这会返回null,因为Client元素内部没有子元素叫Client,直接访问el的属性即可:
正确代码示例:
// 直接从el(即Client元素)获取属性 string testAttr = (string)el.Attribute("TestAttr"); // 或者用空条件运算符避免空引用,属性不存在时返回空字符串 string testAttrValue = el.Attribute("TestAttr")?.Value ?? string.Empty;
解释:
el是查询到的Client元素实例,Attribute("TestAttr")方法会直接返回该元素的TestAttr属性。- 使用
(string)el.Attribute("TestAttr")更安全:如果属性不存在,会返回null而非抛出异常。 - 若使用
.Value,必须先判断属性是否为null,可通过?.和??组合避免空引用。
2. 根据文件扩展名查找TargetId的LINQ查询
针对目标XML结构,需要遍历FileType下的所有FileExtension子元素,匹配指定扩展名后,获取父元素FileType的TargetId属性。
示例代码(方法语法):
// 假设doc是加载好的XDocument对象 string extensionToFind = "jpeg"; string targetId = doc.Descendants("FileExtension") .Where(fe => (string)fe == extensionToFind) .Select(fe => (string)fe.Parent.Attribute("TargetId")) .FirstOrDefault(); // 输出结果 if (!string.IsNullOrEmpty(targetId)) { Console.WriteLine($"匹配到的TargetId: {targetId}"); } else { Console.WriteLine("未找到匹配的扩展名"); }
或者用查询语法:
string targetId = (from fe in doc.Descendants("FileExtension") where (string)fe == extensionToFind select (string)fe.Parent.Attribute("TargetId")) .FirstOrDefault();
解释:
Descendants("FileExtension")会遍历XML中所有FileExtension元素,无需关心层级。- 匹配到目标扩展名后,通过
fe.Parent获取父元素FileType,再提取TargetId属性。 FirstOrDefault()返回第一个匹配结果,无匹配时返回null,避免无结果时抛出异常。- 若XML中有多个
FileType元素,需获取所有匹配结果,可将FirstOrDefault()替换为ToList()。
内容的提问来源于stack exchange,提问作者jc508
相关产品推荐
相关产品推荐

