如何使用PowerShell创建带属性的多层级XML配置文件
PowerShell 生成带属性层级XML配置文件实现
我计划为自己的小型PowerShell应用开发配置XML文件,为此设计了初始化流程:先轮询获取用户输入,再基于用户输入生成配置文件,主程序启动时直接读取该文件数据即可,无需每次启动都重复询问用户。
需要生成的配置文件结构如下:
<CamInfoSettings> <Application> <AppFolder>C:\Temp\01</AppFolder> <PictureFolder>images</PictureFolder> <LogFiles>CamInfo.log</LogFiles> </Application> <Sections> <Count>1</Count> <Section id="1"> <Name>FirstSection Name</Name> <Description>FirstSection Description</Description> <SectionNetworksCount>2</SectionNetworksCount> <FileName>C:\Temp\01\Section1.config</FileName> <SectionIpNetworks> <SectionIpNetwork id="1"> <Network>192.168.12.</Network> <StartIp>22</StartIp> <FinishIp>99</FinishIp> </SectionIpNetwork> <SectionIpNetwork id="2"> <Network>192.168.13.</Network> <StartIp>1</StartIp> <FinishIp>254</FinishIp> </SectionIpNetwork> </SectionIpNetworks> </Section> </Sections> </CamInfoSettings>
目前已经掌握基础的XML创建方法,但卡在了SectionIpNetworks节点下添加多个子元素的环节。由于主程序支持使用多个网络,需要严格按照上述结构生成文件,目前可以创建一个或多个网络节点,但无法为这些节点设置"id"属性,也不能在每个网络节点下添加对应的子元素。
已编写的代码如下,后续循环逻辑卡住:
$SectionEnumber = [int]$Configfile.CamInfoSettings.Sections.Count + 1 $Configfile.SelectSingleNode("CamInfoSettings/Sections/Count").InnerText = $SectionEnumber $newSectionNode = $Configfile.CamInfoSettings.Sections.AppendChild($Configfile.CreateElement("Section")) $newSectionNode.SetAttribute("id",$SectionEnumber) $newSectionName = $newSectionNode.AppendChild($Configfile.CreateElement("Name")) $newSectionName.AppendChild($Configfile.CreateTextNode($SectionName)) | Out-Null $newDescription = $newSectionNode.AppendChild($Configfile.CreateElement("Description")) $newDescription.AppendChild($Configfile.CreateTextNode($SectionDescription)) | Out-Null $newSegmentsCount = $newSectionNode.AppendChild($Configfile.CreateElement("SectionNetworksCount")) $newSegmentsCount.AppendChild($Configfile.CreateTextNode($SectionNetworksCount)) | Out-Null $newFileName = $newSectionNode.AppendChild($Configfile.CreateElement("FileName")) $newFileName.AppendChild($Configfile.CreateTextNode($WritePath + "\" + "Section$SectionEnumber.config")) | Out-Null $newSectionNode.AppendChild($Configfile.CreateElement("SectionNetworks")) | Out-Null $newNetworksNode = $Configfile.SelectSingleNode("CamInfoSettings/Sections/Section[@id=$SectionEnumber]/SectionNetworks") $newNetworksNode.SetAttribute("count",$SectionNetworksCount) foreach ($item in 1..$SectionNetworksCount) { $newNetworksNode.AppendChild($Configfile.CreateElement("SectionNetwork")) |Out-Null # 此处需要创建SectionIpNetwork对应的元素,并设置id属性为$item }
实现代码修正
原有代码存在两个命名不符的基础问题:
- 目标结构的网段父节点名称为
SectionIpNetworks,原代码创建的是SectionNetworks,需修正节点命名 - 循环内需要创建的子节点名称为
SectionIpNetwork,原代码写为SectionNetwork
完整的循环补充代码如下:
# ---------- 修正父节点创建逻辑 ---------- # 替换原代码中创建父节点的两行 $newSectionNode.AppendChild($Configfile.CreateElement("SectionIpNetworks")) | Out-Null $newNetworksNode = $Configfile.SelectSingleNode("CamInfoSettings/Sections/Section[@id=$SectionEnumber]/SectionIpNetworks") # ---------- 提前获取所有网段的用户输入,示例数据可替换为实际轮询逻辑 ---------- $networkConfigList = @() for ($i=1; $i -le $SectionNetworksCount; $i++) { $network = Read-Host "请输入第$i个网段前缀(如192.168.12.)" $startIp = Read-Host "请输入第$i个网段起始IP(如22)" $finishIp = Read-Host "请输入第$i个网段结束IP(如99)" $networkConfigList += @{Network=$network; StartIp=$startIp; FinishIp=$finishIp} } # ---------- 循环生成网段节点 ---------- foreach ($item in 1..$SectionNetworksCount) { # 创建SectionIpNetwork节点并设置id属性 $ipNetworkNode = $Configfile.CreateElement("SectionIpNetwork") $ipNetworkNode.SetAttribute("id", $item) # 拼接Network子节点 $networkNode = $ipNetworkNode.AppendChild($Configfile.CreateElement("Network")) $networkNode.AppendChild($Configfile.CreateTextNode($networkConfigList[$item-1].Network)) | Out-Null # 拼接StartIp子节点 $startIpNode = $ipNetworkNode.AppendChild($Configfile.CreateElement("StartIp")) $startIpNode.AppendChild($Configfile.CreateTextNode($networkConfigList[$item-1].StartIp)) | Out-Null # 拼接FinishIp子节点 $finishIpNode = $ipNetworkNode.AppendChild($Configfile.CreateElement("FinishIp")) $finishIpNode.AppendChild($Configfile.CreateTextNode($networkConfigList[$item-1].FinishIp)) | Out-Null # 将组装完成的网段节点加入父节点 $newNetworksNode.AppendChild($ipNetworkNode) | Out-Null }
内容的提问来源于stack exchange,提问作者Владимир Костяник
相关产品推荐
相关产品推荐

