Циклическая обработка данных API XML неправильно добавляется в массив - PullRequest
0 голосов
/ 13 октября 2018

Вот XML.Я ищу siteid.

<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 для идентификатора клиента, а затем я могу использовать идентификатор клиента, чтобы найти идентификатор сайта для каждого клиента.У некоторых клиентов есть несколько сайтов.

Несмотря на то, что клиенты получены правильно, из-за отсутствия лучшего термина сайты сжаты.

Результаты:

ClientID: 12345
SiteID: 9876543210

Идентификатор сайта должен состоять из двух отдельных номеров: 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 чтобы правильно сохраняться в массиве?

Ответы [ 2 ]

0 голосов
/ 13 октября 2018
[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)
0 голосов
/ 13 октября 2018

tl; dr

Я предлагаю реорганизовать ваш код, чтобы избежать вашей проблемы, и он более эффективен и обеспечивает лучшую инкапсуляцию:

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

Что касается того, что вы пытались :

При присвоении $SiteIDs без модификатора области script ($script:SiteIDs), вы ошибочно создаете локальную $SiteIDs переменную внутри вашей Get-Sites функции.

Учитывая, что области действия см. - но не можете напрямую присваивать - переменные из родительских областей, локальная копия из $SiteIDs, создаваемая присваиванием, наследует тип (и значение) переменнойто же имя из родительской области (см. этот ответ , чтобы узнать больше о области видимости в PowerShell).

Если $SiteIDs действительно является массивом в области действия сценария, локальная копия также будетсоздать массив - но это все равно не изменит массив original в script scope.

Тот факт, что $SiteIDs в вашем случае в итоге содержал конкатенацию строк идентификаторов вашего сайта, говорит о том, что ваш фактический код либо делает не создайте переменную $SiteIDs в области действия скрипта, или она будет string -тип там, а не array (@()) , потому чтоприменение += со строкой в ​​качестве RHS к переменной с типом [string] или ранее не существовавшим выполняет простую конкатенацию строк (добавляет RHS непосредственно к существующему значению, которое по умолчанию равно пустой строке, если переменная

немедленное исправление будет:

  • Убедитесь, что $SiteIDs = @() действительноопределенный в области действия сценария, то есть как массив .

  • Измените $SiteIDs += $siteid на $script:SiteIDs += $siteid, чтобы непосредственно изменить переменную области сценария,как и предполагалось.

Тем не менее, , как правило, лучше избегать обращения к переменным через границы области видимости.ries - используйте параметры и локальные переменные для лучшей инкапсуляции, как показано в верхней части.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...