3

我发现确定解析某些 XML 的最佳方法令人费解。似乎它们有很多可能的方法,但没有一个真正吸引我。

我目前的尝试看起来像这样:

XElement xelement = XElement.Parse(xmlText);
var name = xelement.Element("Employee").Attribute("name").Value;

所以,这行得通。但如果缺少“Employee”元素或“name”属性,则会引发异常。我不想抛出异常。

探索一些在线可用的示例,我看到如下代码:

XElement xelement = XElement.Load("..\\..\\Employees.xml");
IEnumerable<XElement> employees = xelement.Elements();
Console.WriteLine("List of all Employee Names :");
foreach (var employee in employees)
{
    Console.WriteLine(employee.Element("Name").Value);
}

这似乎会遇到完全相同的问题。如果“名称”元素不存在,则Element()返回null并且调用该Value属性时出错。

我需要一些块,比如上面的第一个代码片段。是否有一种简单的方法可以让它工作并且如果缺少某些数据而不抛出异常?

4

5 回答 5

3

在这种情况下,我经常使用扩展方法,因为即使引用为空,它们也能正常工作。我使用了 Anders Abel 在 2012 年初发表的非常好的博客文章“使用扩展方法处理空值”中的扩展方法的略微修改版本:

public static class XElementExtension
{
    public static string GetValueOrDefault(this XAttribute attribute,
                                           string defaultValue = null)
    {
        return attribute == null ? defaultValue : attribute.Value;
    }

    public static string GetAttributeValueOrDefault(this XElement element,
                                                    string attributeName, 
                                                    string defaultValue = null)
    {
        return element == null ? defaultValue : element.Attribut(attributeName)
                                                .GetValueOrDefault(defaultValue);
    }
}

如果要在元素或属性不存在时返回“null”:

var name = xelement.Element("Employee")
                   .GetAttributeValueOrDefault("name" );

如果要在元素或属性不存在时返回默认值:

var name = xelement.Element("Employee")
                    .GetAttributeValueOrDefault("name","this is the default value");

在你的 for 循环中使用:

XElement xelement = XElement.Load("..\\..\\Employees.xml");
IEnumerable<XElement> employees = xelement.Elements();
Console.WriteLine("List of all Employee Names :");
foreach (var employee in employees)
{
    Console.WriteLine(employee.GetAttributeValueOrDefault("Name"));
}
于 2013-01-26T08:06:58.343 回答
3

您可以使用从XAttributeto的显式字符串转换string(如果操作数为 null,则返回 null)和FirstOrDefault方法的组合:

var name = xelement.Elements("Employee")
                   .Select(x => (string) x.Attribute("name"))
                   .FirstOrDefault();

如果没有这样的元素(因为序列将为空,并且FirstOrDefault()将返回 null)或者有一个没有该属性的元素(在这种情况下,您将获得一个带有 null 元素的序列,FirstOrDefault它将返回),则该元素将为 null。

于 2013-01-26T08:29:10.187 回答
2

你总是可以使用 XPath:

string name = xelement.XPathEvaluate("string(Employee/@name)") as string;

这将是属性的值,或者null是否存在Employee@name不存在。

对于迭代示例:

foreach (XNode item in (IEnumerable)xelement.XPathEvaluate("Employee/Name"))
{
     Console.WriteLine(item.Value);
}

XPathEvaluate()只会在这里选择有效的节点,所以你可以放心,它item总是非空的。

于 2013-01-26T16:23:49.757 回答
0

这一切都取决于从 XML 中提取数据后要对数据执行的操作。

您最好查看为 XML 处理而设计的语言,例如 XSLT 和 XQuery,而不是使用 C# 之类的语言,这些语言不是(尽管 Linq 为您提供了一些混合的东西)。使用 C# 或 Java,您总是需要做很多工作来应对 XML 如此灵活的事实。

于 2013-01-26T09:42:27.077 回答
0

使用本机 XmlReader。如果您的问题是读取大型XML文件而不是允许XElement构建对象表示,您可以构建类似Java SAX解析器的东西,它只流式传输XML

例如: http: //www.codeguru.com/csharp/csharp/cs_data/xml/article.php/c4221/Writing-XML-SAX-Parsers-in-C.htm

于 2013-01-26T16:16:38.030 回答