HOWTO · PowerShell
Como Analisar Arquivos XML Usando PowerShell
Este artigo discutirá como podemos analisar arquivos XML corretamente usando o Windows PowerShell.
Nesta página
Para extrair valores de XML no PowerShell, use Select-Xml com uma expressão XPath para uma consulta rápida, System.Xml.XmlDocument quando precisar navegar por um documento carregado ou System.Xml.XmlTextReader para lê-lo sequencialmente como um fluxo. Os exemplos abaixo apenas leem XML. Eles usam um pequeno inventário de computadores e mostram a diferença entre o texto de um elemento e os valores de atributos.
Analisar elementos e atributos XML com Select-Xml
Select-Xml avalia uma expressão XPath e retorna objetos correspondentes. Cada correspondência expõe o nó XML selecionado por meio da propriedade Node. Use InnerText para ler o texto de um elemento; InnerXml retorna a marcação contida nele, o que é útil quando esse conteúdo também precisa ser tratado como XML.
Execute este exemplo:
$path = Join-Path ([System.IO.Path]::GetTempPath()) "computers-$([guid]::NewGuid()).xml"
@'
<Computers>
<Computer name="WINPC-01" ip="127.0.0.1"><Name>WINPC-01</Name></Computer>
<Computer name="WINPC-02" ip="192.168.1.105"><Name>WINPC-02</Name></Computer>
</Computers>
'@ | Set-Content -Path $path -Encoding utf8
Write-Output 'Element names:'
Select-Xml -Path $path -XPath '/Computers/Computer/Name' |
ForEach-Object { $_.Node.InnerText }
Write-Output 'Attribute names:'
Select-Xml -Path $path -XPath '/Computers/Computer' |
ForEach-Object { $_.Node.GetAttribute('name') }
Remove-Item -Path $path
No resultado, o grupo identificado pelo rótulo em inglês “Element names” mostra o texto dos elementos Name; o grupo “Attribute names” mostra os valores do atributo name. Os dois rótulos permanecem em inglês.
Element names:
WINPC-01
WINPC-02
Attribute names:
WINPC-01
WINPC-02
O XPath /Computers/Computer/Name percorre a hierarquia da raiz até cada elemento Name. Para selecionar atributos, selecione os elementos Computer e leia o atributo name de cada nó correspondente. Altere o XPath para corresponder à estrutura do seu XML; os nomes dos elementos e o uso de maiúsculas e minúsculas devem coincidir com o documento. Select-Xml também aceita conteúdo XML pelo parâmetro -Content quando os dados já estão em uma string.
Carregar e consultar XML com System.Xml.XmlDocument
System.Xml.XmlDocument carrega o documento em uma árvore navegável. Isso é conveniente quando um script precisa fazer várias consultas relacionadas ou passar entre nós pais e filhos. A contrapartida é que o documento fica na memória; por isso, um leitor de fluxo pode ser mais adequado para arquivos muito grandes.
Este exemplo carrega um arquivo XML temporário, seleciona cada computador e verifica se há um elemento filho Name antes de lê-lo. Essa verificação é importante quando o esquema XML permite que o elemento esteja ausente: SelectSingleNode() retorna $null quando não há correspondência.
$path = Join-Path ([System.IO.Path]::GetTempPath()) "computers-$([guid]::NewGuid()).xml"
@'
<Computers>
<Computer><Name>WINPC-01</Name></Computer>
<Computer><Ip>192.168.1.105</Ip></Computer>
</Computers>
'@ | Set-Content -Path $path -Encoding utf8
$document = [System.Xml.XmlDocument]::new()
$document.Load($path)
foreach ($computer in $document.SelectNodes('/Computers/Computer')) {
$nameNode = $computer.SelectSingleNode('Name')
if ($null -ne $nameNode) {
Write-Output $nameNode.InnerText
}
else {
Write-Output 'No Name element'
}
}
Remove-Item -Path $path
Use InnerText para obter o valor textual, em vez de InnerXml, que retorna qualquer marcação aninhada no elemento. Se o documento tiver um namespace XML padrão, expressões XPath sem prefixo podem não encontrar seus elementos; crie um XmlNamespaceManager e use um prefixo na consulta.
Ler XML como um fluxo com System.Xml.XmlTextReader
System.Xml.XmlTextReader expõe os nós XML na ordem do documento por meio de um leitor somente de leitura e que avança apenas para a frente. Ele evita construir uma árvore completa do documento, o que pode reduzir o uso de memória com entradas grandes. Como não é possível voltar na leitura, extraia cada valor quando o nó correspondente aparecer. Feche o leitor em um bloco finally para liberar o identificador do arquivo mesmo que o processamento seja interrompido antes do fim.
O exemplo a seguir lê o atributo name de cada elemento inicial Computer. Ele cria seu próprio arquivo XML e descarta o leitor após o processamento.
$path = Join-Path ([System.IO.Path]::GetTempPath()) "computers-$([guid]::NewGuid()).xml"
@'
<Computers>
<Computer name="WINPC-01" ip="127.0.0.1" />
<Computer name="WINPC-02" ip="192.168.1.105" />
</Computers>
'@ | Set-Content -Path $path -Encoding utf8
$reader = [System.Xml.XmlTextReader]::new($path)
try {
while ($reader.Read()) {
if ($reader.NodeType -eq [System.Xml.XmlNodeType]::Element -and
$reader.Name -eq 'Computer') {
Write-Output $reader.GetAttribute('name')
}
}
}
finally {
$reader.Dispose()
Remove-Item -Path $path
}
Para ler o texto de um elemento em vez de um atributo, verifique se o nome do elemento corresponde e leia seu texto enquanto o leitor estiver posicionado nele. ReadString() lê o conteúdo textual e avança o leitor; portanto, leve esse movimento em conta em um loop mais complexo. Descarte o leitor ao terminar; se ele permanecer aberto, o arquivo de entrada poderá continuar bloqueado.
Escolher um método de análise de XML no PowerShell
Escolha Select-Xml quando uma consulta XPath curta for a maneira mais clara de obter alguns nós de um arquivo ou de uma string. Escolha System.Xml.XmlDocument quando precisar de navegação prática pela árvore, de várias consultas ou de acesso a nós relacionados. Escolha System.Xml.XmlTextReader quando puder processar os nós em ordem e quiser evitar carregar uma árvore inteira na memória.
As três abordagens podem ler elementos e atributos. A principal diferença está na forma como expõem o documento: Select-Xml retorna correspondências XPath, XmlDocument permite navegar por uma árvore carregada e XmlTextReader avança por um fluxo. Escolha a abordagem que se adapte ao tamanho do documento e ao padrão das consultas; em seguida, verifique se há nós ou atributos opcionais quando a entrada puder omiti-los.