Цикл Powershell через xml для создания зубчатого массива

Я предполагаю, что это довольно просто, я только начинаю работать с powershell и не могу найти простого решения после нескольких часов поиска в сети.

В основном у меня есть следующий файл xml

<Config>
<System>
<Server>
    <Name>host1</Name> 
    <Service>service1</Service>
    <Service>service2</Service>
</Server>
<Server>
    <Name>host2</Name> 
    <Service>service1</Service>
</Server>
</System>

<System2>
<Server>
    <Name>host1</Name> 
    <Service>service1</Service>
    <Service>service2</Service>
</Server>
<Server>
    <Name>host2</Name> 
    <Service>service1</Service>
     <Service>service2</Service>
     <Service>service3</Service>

</Server>
</System2>
</Config>

И я хотел бы получить содержимое в виде зубчатого массива 2d, чтобы система работала следующим образом:

  • (хост1), (сервис1, сервис2)
  • (хост2), (сервис1)

Можно ли перебрать каждый элемент и создать такой массив?

Я надеюсь сохранить данные, как указано выше, чтобы я мог использовать [0][0] для ссылки на имя хоста, а затем [1][1..x] для ссылки на все службы для этого хоста.

Имеет ли это хоть какой-то смысл?

Любая помощь или лучший подход приветствуется.


person user1910731    schedule 17.12.2012    source источник


Ответы (1)


Вместо этого вы можете подумать об использовании хеш-таблицы. Вы все еще можете перебирать результаты и искать результаты по имени хоста, например:

$xml = [xml]@'
    <Config>
    <System>
    <Server>
        <Name>host1</Name> 
        <Service>service1</Service>
        <Service>service2</Service>
    </Server>
    <Server>
        <Name>host2</Name> 
        <Service>service1</Service>
    </Server>
    </System>

    <System2>
    <Server>
        <Name>host1</Name> 
        <Service>service1</Service>
        <Service>service2</Service>
    </Server>
    <Server>
        <Name>host2</Name> 
        <Service>service1</Service>
        <Service>service2</Service>
        <Service>service3</Service>
    </Server>
    </System2>
    </Config>
'@

$ht = @{}
$hostnameNodes = $xml | Select-Xml -XPath '//Name'
foreach ($node in @($xml | Select-Xml -XPath '//Name'))
{
    $hostname = $node.Node.InnerText.Trim()
    $services = @($node.Node.ParentNode.Service)
    foreach ($service in $services)
    {
        $ht["$hostname"] += @($service.Trim())
    }
}

$ht

Выходы:

Name                           Value                                    
----                           -----                                    
host1                          {service1, service2, service1, service2} 
host2                          {service1, service1, service2, service3} 
person Keith Hill    schedule 17.12.2012
comment
Спасибо за быстрый ответ. Просто чтобы уточнить, как я уже сказал, я довольно новичок во всем этом, ваше решение в основном создаст хеш-таблицу, но заменит одну из пар ключ-значение массивом сервисов? - person user1910731; 17.12.2012
comment
Он создает запись для каждого имени хоста, и значением этой записи будет массив имен служб. - person Keith Hill; 17.12.2012
comment
Блин, спасибо большое, очень ценю вашу помощь и советы. Я обязательно займусь этим завтра. Я только что протестировал приведенный выше код и, похоже, присваивает службам нули, поэтому я предполагаю, что мне нужно немного поиграть с ним, но все это часть обучения :-) - person user1910731; 17.12.2012
comment
Извиняюсь за дополнительный вопрос, я понял, что мне действительно нужна возможность извлекать все данные в хеш-таблицу для конкретной системы... так, например, только данные в ‹System› ...... . ‹/System›, поэтому в основном создайте таблицу has для каждого имени хоста и связанных служб, составляющих систему. - person user1910731; 18.12.2012
comment
если я изменю части Select-Xml -XPath, смогу ли я добиться этого? Спасибо еще раз за помощь - person user1910731; 18.12.2012
comment
Отвечая на мой собственный вопрос сейчас, я могу использовать Select-Xml -XPath '//Config/System1/Server/Name' для фильтрации результатов в системе. Спасибо за всю помощь Кит - person user1910731; 18.12.2012