循环遍历 API XML 数据未正确添加到数组中



这是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)

最新更新