Linq To Xml 空属性检查

10
<books>
   <book name="Christmas Cheer" price="10" />
   <book name="Holiday Season" price="12" />
   <book name="Eggnog Fun" price="5" special="Half Off" />
</books>

我想使用LINQ解析这个,我很好奇其他人处理特殊情况时使用的方法。我目前处理此问题的方式是:

var books = from book in booksXml.Descendants("book")
                        let Name = book.Attribute("name") ?? new XAttribute("name", string.Empty)
                        let Price = book.Attribute("price") ?? new XAttribute("price", 0)
                        let Special = book.Attribute("special") ?? new XAttribute("special", string.Empty)
                        select new
                                   {
                                       Name = Name.Value,
                                       Price = Convert.ToInt32(Price.Value),
                                       Special = Special.Value
                                   };

我想知道是否有更好的方法来解决这个问题。

谢谢,

  • Jared
3个回答

11

您可以将该属性强制转换为 string。如果该属性缺失,则会返回 null,后续代码应检查是否为 null,否则它将直接返回该值。

请尝试此方法:

var books = from book in booksXml.Descendants("book")
            select new
            {
                Name = (string)book.Attribute("name"),
                Price = (string)book.Attribute("price"),
                Special = (string)book.Attribute("special")
            };

太棒了!我喜欢它。谢谢。 - Howel

4
如何使用扩展方法封装缺失属性的情况:
public static class XmlExtensions
{
    public static T AttributeValueOrDefault<T>(this XElement element, string attributeName, T defaultValue)
    {
        var attribute = element.Attribute(attributeName);
        if (attribute != null && attribute.Value != null)
        {
            return (T)Convert.ChangeType(attribute.Value, typeof(T));
        }

        return defaultValue;
    }
}

请注意,只有当T是通过IConvertible接口可转换为字符串的类型时,此方法才能正常工作。如果您希望支持更通用的类型转换情况,可能需要使用TypeConverter类。如果类型转换失败,将会抛出异常。如果您想让这些情况也返回默认值,则需要进行额外的错误处理。

我使用了这个变体,但是使用了 XAttribute Attribute<T>(this XElement element, XName name, T defaultValue)。如果失败了,就创建一个 new XAttribute(name,defaultValue);。然后重载就在原来的旁边。 - Dominic Zukiewicz

1
在C#6.0中,您可以使用单子Null-条件运算符?。应用于您的示例后,它看起来像这样:
var books = from book in booksXml.Descendants("book")
            select new
            {
                Name = book.Attribute("name")?.Value ?? String.Empty,
                Price = Convert.ToInt32(book.Attribute("price")?.Value ?? "0"),
                Special = book.Attribute("special")?.Value ?? String.Empty
            };

您可以在标题为 Null-conditional operators 的部分这里阅读更多相关内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接