O XML (eXtensible Markup Language) é um formato de dados amplamente utilizado para representar informações estruturadas, como arquivos de configuração, respostas de APIs e troca de dados entre sistemas. No PowerShell, o suporte a XML é robusto e integrado, permitindo que você carregue, manipule e transforme documentos XML com facilidade. Nesta aula, vamos explorar as principais técnicas para trabalhar com XML, desde a leitura até a navegação em estruturas complexas, além de discutir casos de uso reais.

Dominar XML no PowerShell é essencial para quem lida com automação de tarefas administrativas, pois muitos sistemas e serviços utilizam XML como formato padrão. Você aprenderá a carregar arquivos XML, a acessar elementos e atributos, a modificar dados e a salvar as alterações. Ao final, você estará apto a integrar XML em seus scripts de forma eficiente.

Visão geral

O PowerShell trata documentos XML como objetos do tipo System.Xml.XmlDocument. Isso significa que, após carregar um XML, você pode acessar seus elementos como propriedades de objetos, o que torna a navegação muito intuitiva. Além disso, o PowerShell oferece aliases e cmdlets como Select-Xml para consultas XPath, e a capacidade de converter XML em objetos personalizados com ConvertTo-Xml.

Para começar, é importante entender a diferença entre carregar um XML como string e como documento. Quando você usa [xml] para converter uma string XML, o PowerShell cria um objeto XML que pode ser navegado diretamente. Por exemplo:

$xmlString = @'
<root>
  <item>Valor 1</item>
  <item>Valor 2</item>
</root>
'@
$xml = [xml]$xmlString
$xml.root.item

Esse objeto é um documento completo, com métodos para navegação e manipulação. Para arquivos, você pode usar Get-Content ou [xml](Get-Content -Raw) para carregar o conteúdo.

Lendo XML

Existem várias formas de ler um arquivo XML no PowerShell. A mais comum é usar o tipo [xml] com o conteúdo do arquivo. Você pode usar Get-Content com a opção -Raw para ler todo o arquivo como uma única string e então convertê-lo para XML. Por exemplo, suponha que temos o arquivo config.xml com o seguinte conteúdo:

<configuracoes>
  <app>
    <nome>MeuApp</nome>
    <versao>1.0.0</versao>
  </app>
  <servidor>
    <host>localhost</host>
    <porta>8080</porta>
  </servidor>
</configuracoes>

Para ler e acessar esses dados, você pode fazer:

$caminho = "C:\scripts\config.xml"
$xml = [xml](Get-Content -Path $caminho -Raw)
$xml.configuracoes.app.nome
$xml.configuracoes.servidor.porta

Outra abordagem é usar o cmdlet Select-Xml com uma consulta XPath. Isso é útil quando você precisa extrair dados específicos de um documento grande. Por exemplo:

$xmlDoc = [xml](Get-Content -Path $caminho -Raw)
$resultado = Select-Xml -Xml $xmlDoc -XPath "//app/nome"
$resultado.Node.InnerText

Além disso, você pode usar [System.Xml.XmlDocument]::Load() para carregar diretamente de um arquivo, o que é mais eficiente para arquivos grandes:

$xmlDoc = New-Object System.Xml.XmlDocument
$xmlDoc.Load($caminho)

Essa técnica evita a conversão de string e é recomendada para arquivos grandes.

Navegando

Navegar em um documento XML no PowerShell é feito principalmente por meio de propriedades e métodos do objeto XmlDocument. A estrutura hierárquica do XML é acessível como uma árvore de objetos. Por exemplo, para acessar o elemento nome dentro de app, você usa $xml.configuracoes.app.nome. Isso funciona porque o PowerShell expõe os elementos filhos como propriedades.

Para lidar com listas de elementos (quando há vários filhos com o mesmo nome), você pode usar indexação. Por exemplo, se tiver múltiplos itens <item>, pode acessar o primeiro com $xml.root.item[0]. Você também pode iterar sobre eles com foreach.

Atributos de elementos são acessados como propriedades, mas precedidos por um símbolo @. Por exemplo, para um elemento <livro id="1">, você acessa o atributo com $xml.livro.id (na verdade, o PowerShell trata atributos como propriedades nomeadas, então você pode usar $xml.livro.id diretamente). No entanto, para evitar conflitos com elementos filhos, é comum usar GetAttribute() ou acessar via .id.

Vamos ver um exemplo prático de navegação:

$xmlString = @'
<biblioteca>
  <livro id="1">
    <titulo>O Senhor dos Anéis</titulo>
    <autor>J.R.R. Tolkien</autor>
  </livro>
  <livro id="2">
    <titulo>1984</titulo>
    <autor>George Orwell</autor>
  </livro>
</biblioteca>
'@
$xml = [xml]$xmlString

# Acessar o primeiro livro
$primeiroLivro = $xml.biblioteca.livro[0]
$primeiroLivro.titulo  # O Senhor dos Anéis
$primeiroLivro.id      # 1

# Iterar sobre todos os livros
foreach ($livro in $xml.biblioteca.livro) {
    Write-Host "$($livro.titulo) - $($livro.autor)"
}

Outra técnica poderosa é usar XPath para navegar e selecionar nós. O cmdlet Select-Xml é ideal para isso. Por exemplo, para selecionar todos os títulos de livros:

$selecionados = Select-Xml -Xml $xml -XPath "//titulo"
$selecionados | ForEach-Object { $_.Node.InnerText }

Isso retorna uma lista de nós que correspondem à consulta XPath. Você também pode usar XPath para filtrar com base em atributos: //livro[@id='2'].

Casos de uso

O XML é usado em muitos cenários do mundo real, e o PowerShell pode interagir com eles de forma eficaz. Um dos casos mais comuns é a leitura de arquivos de configuração. Muitos aplicativos, como o IIS, usam XML para suas configurações. Você pode usar PowerShell para ler e modificar essas configurações de forma programática.

Outro caso é a integração com APIs que retornam XML, como alguns serviços REST antigos. O PowerShell pode consumir essas respostas e processá-las. Por exemplo, você pode fazer uma solicitação HTTP com Invoke-RestMethod e, se o retorno for XML, convertê-lo para objeto XML e navegar.

Além disso, o XML é usado em arquivos de log, relatórios e até mesmo em formatos de documentos como o DOCX (que é um arquivo ZIP contendo XML). O PowerShell pode extrair e manipular esses XMLs.

Vamos ver um exemplo prático de leitura de configuração e modificação:

# Suponha que temos um arquivo de configuração
$caminhoConfig = "C:\scripts\app.config"
$xmlConfig = [xml](Get-Content -Path $caminhoConfig -Raw)

# Alterar o valor de uma configuração
$xmlConfig.configuracao.appSettings.add | Where-Object { $_.key -eq "timeout" } | ForEach-Object { $_.value = "30" }

# Salvar o arquivo
$xmlConfig.Save($caminhoConfig)

Outro uso comum é a geração de XML para exportação de dados. Você pode criar um documento XML a partir de objetos do PowerShell usando ConvertTo-Xml:

$processos = Get-Process | Select-Object -First 3
$xml = $processos | ConvertTo-Xml -NoTypeInformation
$xml.Save("C:\scripts\processos.xml")

Isso cria um XML estruturado com os dados dos processos.

Boas práticas e observações finais

Ao trabalhar com XML no PowerShell, é importante considerar a codificação e a validação. Sempre use -Raw ao ler arquivos para evitar problemas de quebra de linha. Para arquivos grandes, prefira XmlDocument.Load() para melhor desempenho.

Outra boa prática é usar XPath quando você precisar de consultas complexas, pois é mais eficiente e expressivo do que navegar manualmente. Além disso, ao modificar XML, lembre-se de salvar o documento com Save() para persistir as alterações.

Por fim, sempre trate erros ao carregar XML, pois arquivos malformados podem causar exceções. Use try/catch para capturar e lidar com esses erros.

Referências

Exercícios

  1. Escreva um script que carregue o arquivo XML fornecido abaixo e exiba o valor do elemento nome dentro de app.
    <configuracoes>
      <app>
        <nome>MeuApp</nome>
        <versao>1.0.0</versao>
      </app>
    </configuracoes>

    ✓ Resposta:
    $xml = [xml]@'
    <configuracoes>
      <app>
        <nome>MeuApp</nome>
        <versao>1.0.0</versao>
      </app>
    </configuracoes>
    '@
    $xml.configuracoes.app.nome
  2. Dado o XML de uma biblioteca, exiba o título do livro com id="2".
    <biblioteca>
      <livro id="1"><titulo>O Senhor dos Anéis</titulo></livro>
      <livro id="2"><titulo>1984</titulo></livro>
    </biblioteca>

    ✓ Resposta:
    $xml = [xml]@'
    <biblioteca>
      <livro id="1"><titulo>O Senhor dos Anéis</titulo></livro>
      <livro id="2"><titulo>1984</titulo></livro>
    </biblioteca>
    '@
    $xml.biblioteca.livro | Where-Object { $_.id -eq "2" } | Select-Object -ExpandProperty titulo
  3. Carregue um arquivo XML chamado dados.xml e use Select-Xml para contar quantos elementos <item> existem.

    ✓ Resposta:
    $xml = [xml](Get-Content -Path "dados.xml" -Raw)
    $itens = Select-Xml -Xml $xml -XPath "//item"
    $itens.Count
  4. Modifique o XML de configuração do exercício 1, alterando a versão para "2.0.0" e salve em um novo arquivo.

    ✓ Resposta:
    $xml = [xml]@'
    <configuracoes>
      <app>
        <nome>MeuApp</nome>
        <versao>1.0.0</versao>
      </app>
    </configuracoes>
    '@
    $xml.configuracoes.app.versao = "2.0.0"
    $xml.Save("C:\scripts\novo_config.xml")
  5. Crie um script que gere um XML a partir de uma lista de objetos (por exemplo, processos) usando ConvertTo-Xml e salve em um arquivo.

    ✓ Resposta:
    $processos = Get-Process | Select-Object -First 3
    $xml = $processos | ConvertTo-Xml -NoTypeInformation
    $xml.Save("C:\scripts\processos.xml")