XML Configuration Provider
These features are only available if the xml feature is activated
The XmlConfigurationProvider
supports loading configuration from a *.xml
file.
The following code adds several configuration providers, including a couple of *.xml
files:
fn main() {
let name = env::var("ENVIRONMENT").or_else("production");
let config = DefaultConfigurationBuilder::new()
.add_xml_file("MyXmlConfig.xml".is().optional())
.add_xml_file(format!("MyXmlConfig.{}.xml", name).is().optional())
.add_env_vars()
.add_command_line()
.build()
.unwrap();
}
The XML configuration files have a few special rules that are different from other configuration providers:
- XML namespaces are not supported on elements or attributes
- The
Name
attribute (case-insensitive) is considered as a surrogate key in lieu of the element it is applied to - Duplicate key-value combinations are ambiguous and not allowed
- Repeating elements with different values are considered array-like
Consider the following configuration file:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<MyKey>MyXMLFile Value</MyKey>
<Position>
<Title>Title from MyXMLFile</Title>
<Name>Name from MyXMLFile</Name>
</Position>
<Logging>
<LogLevel>
<Default>Information</Default>
<App>Warning</App>
</LogLevel>
</Logging>
</configuration>
The following code displays several of the preceding configuration settings:
let my_key_value = config.get("MyKey").unwrap().as_str();
let title = config.get("Position:Title").unwrap().as_str();
let name = config.section("Position").get("Name").unwrap().as_str();
let default_log_level = config.get("Logging:LogLevel:Default").unwrap().as_str();
println!("MyKey value: {}\n\
Title: {}\n\
Name: {}\n\
Default Log Level: {}",
my_key_value,
title,
name,
default_log_level);
Repeating elements that use the same element name work if the name
attribute is used to distinguish the elements:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<section name="section0">
<key name="key0">value 00</key>
<key name="key1">value 01</key>
</section>
<section name="section1">
<key name="key0">value 10</key>
<key name="key1">value 11</key>
</section>
</configuration>
The following code reads the previous configuration file and displays the keys and values:
use config::{*, ext::*};
fn main() {
let config = DefaultConfigurationBuilder::new()
.add_xml_file("MyXmlConfig2.xml")
.build()
.unwrap();
let val00 = config.get("section:section0:key:key0").unwrap().as_str();
let val01 = config.get("section:section0:key:key1").unwrap().as_str();
let val10 = config.get("section:section1:key:key0").unwrap().as_str();
let val11 = config.get("section:section1:key:key1").unwrap().as_str();
println!("section:section0:key:key0 value: {}\n\
section:section0:key:key1 value: {}\n\
section:section1:key:key0 value: {}\n\
section:section1:key:key1 value: {}",
val00
val01
val10
val11);
}
If the name
attribute were not used, then the elements would be treated as array-like:
- section:0:key:0
- section:0:key:1
- section:1:key:0
- section:1:key:1
Attributes can also be used to supply values:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<key attribute="value" />
<section>
<key attribute="value" />
</section>
</configuration>
The previous configuration file loads the following keys with value of value
:
- key:attribute
- section:key:attribute