如果找不到元素,如何解析xml文件并返回默认值

本文关键字:文件 返回 默认值 xml 何解析 找不到 元素 如果 | 更新日期: 2023-09-27 18:29:19

我用C#编写了一个简单的方法来解析给定的xml文件并返回特定节点的值。它工作正常,但如果找不到节点,我也希望返回默认值,而不是抛出异常。我该怎么做?这个方法能写得更好吗?谢谢你提供的任何帮助。约翰·

public static string ReadConfigurationFile(string configurationFileName, string root, string section, string name)
{
    try
    {
        String currentDirectory = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
        configFilePath = Directory.GetParent(currentDirectory) + configurationFolder + configurationFileName;
        XDocument configXML = XDocument.Load(configFilePath);
        var result = from setting in
                         configXML.Descendants(root)
                            .Descendants(section)
                     select setting.Element(name).Attribute("value").Value;
        return result.First();
    }
    catch (Exception ex)
    {
        return string.Empty;
    }
}

下面是我解析的XML文件示例:

<?xml version='1.0' encoding='utf-8'?>
<automationSettings>
    <vmDomain>
        <domainName value = "Domain"/>
        <domainUsername value = "username"/>
        <domainPassword value = "password"/>
    </vmDomain>
</automationSettings>

如果找不到元素,如何解析xml文件并返回默认值

让我们从消除异常"处理"开始。找不到节点是一个"合理的预期"错误,我们将确保不会导致异常。可能应该抛出其他异常,例如根本找不到文件,或者文件不是有效的XML。

接下来,让我们停止使用查询表达式——当您只使用select子句时,它并不能真正为您带来任何好处。

作为下一步,我将停止分配给configFilePath,它可能是一个字段。将该字段作为副作用写入对我来说似乎是一个非常糟糕的主意。让我们使用Path.Combine来组合路径的位。。。

所以现在我们有了:

// Work in progress!
public static string ReadConfigurationFile(
    string configurationFileName,
    string root,
    string section,
    string name)
{
    string currentDirectory = Path.GetDirectoryName(
        Assembly.GetExecutingAssembly().Location);
    var fullConfigPath = Path.Combine(
        Directory.GetParent(currentDirectory),
        configurationFolder,
        configurationFileName);
    var configXml = XDocument.Load(fullConfigPath);
    return configXml.Descendants(root)
                    .Descendants(section)
                    .Select(x => x.Element(name).Attribute("value").Value
                    .First();
}

现在,如果找不到元素或属性,就会抛出异常。我们可以这样解决:

return configXml.Descendants(root)
                .Descendants(section)
                .Elements(name)
                .Select(x => (string) x.Attribute("value"))
                .FirstOrDefault();

现在,如果Elements()返回一个空序列,那么就没有什么可选择的,FirstOrDefault()将返回null。如果元素,并且它没有value属性,则x.Attribute("value")将返回null,并且从XAttributestring的显式转换将返回null。

当我们这样做的时候,我们只使用configXml进行一次调用,所以让我们内联一下,留下:

public static string ReadConfigurationFile(
    string configurationFileName,
    string root,
    string section,
    string name)
{
    string currentDirectory = Path.GetDirectoryName(
        Assembly.GetExecutingAssembly().Location);
    var fullConfigPath = Path.Combine(
        Directory.GetParent(currentDirectory),
        configurationFolder,
        configurationFileName);
    return XDocument.Load(fullConfigPath)
                    .Descendants(root)
                    .Descendants(section)
                    .Elements(name)
                    .Select(x => (string) x.Attribute("value"))
                    .FirstOrDefault();
}

现在,它返回null,而不是原始代码所返回的空字符串。我认为这样更好,因为:

  • 它允许调用者区分"提供了设置但为空"answers"未提供设置"
  • 它允许调用者使用null合并运算符来指定默认值:

    var setting = ReadConfigurationFile("a", "b", "c", "d") ?? "some default value";