如果未找到元素,如何解析 xml 文件和 return 默认值
How to parse an xml file and return default value if no element found
我用 C# 编写了一个简单的方法来解析给定的 xml 文件和 return 特定节点的值。它工作正常,但如果找不到节点而不是抛出异常,我还想 return 默认值。我怎样才能做到这一点?方法能不能写的更好?
感谢您提供的任何帮助。
约翰
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>
让我们从消除异常开始 "handling"。找不到节点是一个 "reasonable to expect" 错误,我们要确保该错误不会导致异常。其他异常 - 例如根本找不到文件或无效 XML - 可能应该被抛出。
接下来,让我们停止使用查询表达式 - 当您只使用 select
子句时,它不会真正给您带来任何好处。
作为下一步,我将停止分配给 configFilePath
,这大概是一个字段。作为 side-effect 写入该字段对我来说似乎是一个非常糟糕的主意。让我们也使用 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()
return 是一个空序列,select 将没有任何内容,而 FirstOrDefault()
将 return 为空。如果 是 元素并且它没有 value
属性,则 x.Attribute("value")
将 return 为 null,并且从 [=21 显式转换=] 到 string
将 return 为空。
虽然我们这样做,但我们只使用 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();
}
现在,returns null
而不是原始代码所做的空字符串。我认为这样更好,因为:
- 它允许调用者区分 "the setting was provided but empty" 和 "the setting wasn't provided"
它允许调用者使用null-coalescing运算符来指定一个默认值:
var setting = ReadConfigurationFile("a", "b", "c", "d") ?? "some default value";
我用 C# 编写了一个简单的方法来解析给定的 xml 文件和 return 特定节点的值。它工作正常,但如果找不到节点而不是抛出异常,我还想 return 默认值。我怎样才能做到这一点?方法能不能写的更好? 感谢您提供的任何帮助。 约翰
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>
让我们从消除异常开始 "handling"。找不到节点是一个 "reasonable to expect" 错误,我们要确保该错误不会导致异常。其他异常 - 例如根本找不到文件或无效 XML - 可能应该被抛出。
接下来,让我们停止使用查询表达式 - 当您只使用 select
子句时,它不会真正给您带来任何好处。
作为下一步,我将停止分配给 configFilePath
,这大概是一个字段。作为 side-effect 写入该字段对我来说似乎是一个非常糟糕的主意。让我们也使用 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()
return 是一个空序列,select 将没有任何内容,而 FirstOrDefault()
将 return 为空。如果 是 元素并且它没有 value
属性,则 x.Attribute("value")
将 return 为 null,并且从 [=21 显式转换=] 到 string
将 return 为空。
虽然我们这样做,但我们只使用 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();
}
现在,returns null
而不是原始代码所做的空字符串。我认为这样更好,因为:
- 它允许调用者区分 "the setting was provided but empty" 和 "the setting wasn't provided"
它允许调用者使用null-coalescing运算符来指定一个默认值:
var setting = ReadConfigurationFile("a", "b", "c", "d") ?? "some default value";