解析XML的有效方法

时间:2013-01-26 06:45:59

标签: c# .net xml linq-to-xml

我发现确定解析某些XML的最佳方法令人费解。看来他们有很多可能的方式,没有人真正点击过我。

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

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

所以,这很有效。但是如果缺少“Employee”元素或“name”属性,它会抛出异常。我不想抛出异常。

探索一些examples available online,我看到这样的代码:

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);
}

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

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

5 个答案:

答案 0 :(得分:3)

我经常在这种情况下使用扩展方法,因为即使引用为null也可以工作。我使用了一个稍微修改过的版本的扩展方法来自Anders Abel从2012年初开始的非常好的博客文章“Null Handling with Extension Methods”:

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"));
}

答案 1 :(得分:3)

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

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

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

答案 2 :(得分:2)

你总是可以使用XPath:

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

这可以是属性的值,如果nullEmployee不存在,则为@name

对于迭代示例:

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

XPathEvaluate()只会在此处选择有效节点,因此您可以确信item始终为非空。

答案 3 :(得分:0)

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

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

答案 4 :(得分: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