我使用 XML 文件作为我的 PowerShell 脚本的配置文件(基于 rkeithhill.wordpress.com 中找到的博客文章) 。我的一些脚本共享相同的设置,我想包含来自外部 XML 文件的这些设置。我所做的是:
<?xml version="1.0" standalone="no" ?>
<!DOCTYPE doc [
<!ENTITY shareddata SYSTEM "shared.xml">
]>
<configuration >
<appSettings >
&shareddata;
<add key="motorcycle" value="Husqvarna TE610" />
<add key="car" value="Ford Mondeo" />
</appSettings>
</configuration>
并且shared.xml
文件包含(仅一行):
<add key="backhoe" value="Volvo BM 430 Hymas" />
使用以下代码片段加载 XML 并将其打印到控制台:
$config = [xml](get-content $path)
$text = $config.OuterXml
Write-Verbose "[LoadConfig] $text"
输出为:
VERBOSE: [LoadConfig] <?xml version="1.0" standalone="no"?>
<!DOCTYPE doc[
<!ENTITY shareddata SYSTEM "shared.xml">
]>
<configuration><appSettings>&shareddata;
<add key="motorcycle" value="Husqvarna TE610" />
<add key="car" value="Ford Mondeo" /></appSettings> </configuration>
我加载 XML 的方式不包括 shared.xml
的内容,但它确实解析 DOCTYPE
标记,因为如果我恢复到无效文件,它就会将会失败。
那么,我怎样才能让 PowerShell 完全包含 XML 片段,以便 loadconfig
也能找到我的反铲挖掘机的键和值?
我也尝试过
$Document = ( Select-Xml -Path myfile.xml -XPath / ).Node
但只要我在配置文件中有 &shareddata;
它就不会加载任何内容:
最佳答案
我在 C# 中尝试了你的示例,但它也不起作用。这在 C# 中有效,但是一旦您将 shared.xml
更改为包含 TEST VALUE
值(即只允许简单值,而不是 xml),但它在 PS 中仍然不起作用:
<configuration >
<appSettings >
<test>&shareddata;</test>
<add key="motorcycle" value="Husqvarna TE610" />
<add key="car" value="Ford Mondeo" />
</appSettings>
</configuration>
使用此代码:
$doc = new-object System.Xml.XmlDocument
$doc.Load("D:\config.xml")
$doc.configuration.appSettings.add
key value
--- -----
motorcycle Husqvarna TE610
car Ford Mondeo
C# 中的相同示例有效:
XmlDocument doc = new XmlDocument();
doc.Load("d:\\config.xml");
var x = doc["configuration"]["appSettings"]["test"];
Console.WriteLine(x.InnerText);
输出
TEST VALUE
Powershell 似乎设置了 doc.XmlResolver = null;
选项来防止与安全相关的问题,您可以在 PS 中看到 $doc.XmlResolver
不返回任何内容。我没有成功通过 $doc.XmlResolver = new-object System.Xml.XmlUrlResolver
手动设置解析器。
现在,
您可以使用变量替换来达到效果:
<configuration >
<appSettings >
$shared_xml
<add key="motorcycle" value="Husqvarna TE610" />
<add key="car" value="Ford Mondeo" />
</appSettings>
</configuration>
$shared_xml = Get-Content 'D:\shared.xml'
[xml]$config = $ExecutionContext.InvokeCommand.ExpandString((gc $path))
如果您枚举配置 block 中的变量并加载适当的文件,您可以使这变得更容易。这样您就可以事先不知道包含哪些文件。
现在,
这一切看起来都很麻烦,除非有一些正常的解决方案来解决解析器问题。但老实说,将配置保留在 XML 中的想法在很多层面上都是错误的。当你可以使用 powershell 配置时为什么要使用 XML:
$config = @{ }
$config.motorcycle = 'Husqvarna TE610'
$config.car = 'Ford Mondeo'
$shared = @{}
$shared.backhoe = "Volvo BM 430 Hymas"
$config + $shared
输出
Name Value
---- -----
backhoe Volvo BM 430 Hymas
car Ford Mondeo
motorcycle Husqvarna TE610
您可以使其遵循“包含”模式,例如:
config.ps1
$config = @{
motorcycle = 'Husqvarna TE610'
car = 'Ford Mondeo'
}
. shared1.ps1
...
. sharedN.ps1
共享N.ps1
$config.sharedN_cfg1 = 1
$config.sharedN_cfg2 = 2
如果从那时起您确实需要 XML,您可以随后使用 ConvertTo-CliXML
等。
如果您仍然想追求自己的方向,我建议您查看 XInclude (你需要第三次党代表大会才能完成这项工作)。
关于xml - 如何将 XML 片段包含到 XML 文档中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30591166/