这是XML。我正在寻找网站ID。
<result created="2018-10-13T13:11:18-05:00" host="redacted" status="OK">
<items>
<site>
<siteid>399700</siteid>
<name>
<![CDATA[ Warehouse ]]>
</name>
<connection_ok>1</connection_ok>
</site>
<site>
<siteid>547401</siteid>
<name>
<![CDATA[ Monterey Park ]]>
</name>
<connection_ok>1</connection_ok>
</site>
</items>
</result>
若要获取要查找的数据,我首先需要遍历 XML 以获取客户端 ID,然后可以使用客户端 ID 查找每个客户端的站点 ID。某些客户端有多个站点。
虽然客户端是正确获得的,但由于缺乏更好的术语,这些站点被压缩。
结果:
客户端 ID: 12345 站点 ID:9876543210
站点 ID 应为两个单独的编号:98765 43210
以下是我正在使用的两个函数:
$ClientsIDs = @()
$SiteIDs = @()
function Get-Clients() {
$clientdata = Invoke-RestMethod -Uri ($baseurl + $lc)
$clientid = $clientdata.result.items.client.clientid
$Script:ClientsIDs += $clientid
Write-Output("Client ID: " + $ClientsIDs)
}
function Get-Sites() {
foreach ($id in $Global:ClientsIDs) {
$sitedata = Invoke-RestMethod -Uri ($baseurl + $ls + $id)
$siteid = $sitedata.result.items.site.siteid
$SiteIDs += $siteid
}
Write-Output("Site ID: " + $SiteIDs)
}
Get-Clients
Get-Sites
(仅不显示 URL。Write-Output
只是为了我的利益,以确保正确收集数据。它们最终将被删除。
如何使$sitedid
正确保存在数组中?
tl;博士
我建议重构你的代码,这样可以避免你的问题,并且更有效率并提供更好的封装:
function Get-Sites() {
# Note: Also consider passing the parent-scope
# $ClientsIDs, $baseurl, $ls variables as *parameters* instead.
foreach ($id in $ClientsIDs){
$sitedata = Invoke-RestMethod -Uri ($baseurl + $ls + $id)
# Implicitly output each site ID, which by
# virtue of being inside a foreach loop outputs
# all of them as an array.
$sitedata.result.items.site.siteid
}
}
# If you wanted to interpret the IDs as *numbers*, you
# could use type [int[]], for instance
[array] $SiteIDs = Get-Sites
至于你尝试过的:
通过分配给没有作用域修饰符script
($script:SiteIDs
$SiteIDs
(,您错误地在Get-Sites
函数中创建了一个局部$SiteIDs
变量。
鉴于作用域可以看到(但不能直接分配给(父作用域中的变量,则分配创建的$SiteIDs
的本地副本将从父作用域继承同名变量的类型(和值((请参阅此答案,了解有关在 PowerShell 中限定范围的详细信息(。
如果$SiteIDs
确实是脚本作用域中的数组,则本地副本也会创建一个数组- 但这仍然不会修改脚本作用域中的原始数组。
在您的案例中,$SiteIDs
最终包含站点 ID 的字符串串联这一事实表明,您的实际代码要么不会在脚本范围内创建$SiteIDs
变量,要么在那里是字符串类型,而不是数组(@()
(,因为将带有字符串的+=
作为 RHS 应用于[string]
类型化或以前不存在的变量会执行简单的字符串连接(附加 RHS直接到现有值,如果变量不存在,则默认为空字符串(。
立即的解决方法是:
确保
$SiteIDs = @()
在脚本范围内真正定义,即定义为数组。将
$SiteIDs += $siteid
更改为$script:SiteIDs += $siteid
以便按预期直接修改脚本范围变量。
也就是说,通常最好避免跨范围边界引用变量- 使用参数和局部变量以获得更好的封装,如顶部所示。
[array]$SiteIDs += $siteid
# or
function Get-Sites() {
$SiteIDs=@()
foreach ($id in $Global:ClientsIDs){
...
$SiteIDs += $siteid
# or; for better performance
function Get-Sites() {
$SiteIDs=New-Object System.Collections.ArrayList
foreach ($id in $Global:ClientsIDs){
...
$SiteIDs.add($siteid)