HOWTO · PowerShell
Cómo analizar archivos XML usando PowerShell
Este artículo discutirá cómo podemos analizar archivos XML correctamente utilizando Windows PowerShell.
En esta página
Para extraer valores de XML en PowerShell, usa Select-Xml con una expresión XPath para consultas rápidas, System.Xml.XmlDocument si necesitas recorrer un documento cargado o System.Xml.XmlTextReader para leerlo secuencialmente como un flujo. Los ejemplos solo leen XML. Usan un pequeño inventario de equipos y muestran la diferencia entre el texto de un elemento y los valores de sus atributos.
Analizar elementos y atributos XML con Select-Xml
Select-Xml evalúa una expresión XPath y devuelve objetos que representan las coincidencias. Cada objeto expone el nodo XML seleccionado mediante la propiedad Node. Usa InnerText para leer el texto de un elemento; InnerXml devuelve el marcado contenido dentro de él, lo cual resulta útil cuando necesitas ese contenido como XML.
Ejecuta este ejemplo:
$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
Element names:
WINPC-01
WINPC-02
Attribute names:
WINPC-01
WINPC-02
La expresión XPath /Computers/Computer/Name recorre la jerarquía desde la raíz hasta cada elemento Name. Para seleccionar atributos, selecciona los elementos Computer y lee el atributo name de cada nodo coincidente. Ajusta la expresión XPath a la estructura de tu XML; los nombres de los elementos y las mayúsculas y minúsculas deben coincidir con los del documento. Select-Xml también acepta contenido XML mediante el parámetro -Content cuando los datos ya están en una cadena.
En la salida del ejemplo, los grupos aparecen con las etiquetas en inglés “Element names” y “Attribute names”: el primero muestra el texto de los elementos Name y el segundo, los valores del atributo name.
Cargar y consultar XML con System.Xml.XmlDocument
System.Xml.XmlDocument carga el documento en un árbol que se puede recorrer. Es práctico cuando un script necesita realizar varias consultas relacionadas o moverse entre nodos padre e hijo. Como el documento se mantiene en memoria, un lector de flujo puede ser más adecuado para archivos muy grandes.
Este ejemplo carga un archivo XML temporal, selecciona cada equipo y comprueba si tiene un elemento hijo Name antes de leerlo. Esta comprobación es importante si el esquema XML permite que ese elemento no esté presente: SelectSingleNode() devuelve $null cuando no encuentra ninguna coincidencia.
$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
Usa InnerText para obtener el valor de texto en lugar de InnerXml, que devuelve cualquier marcado anidado dentro del elemento. Si el documento tiene un espacio de nombres XML predeterminado, es posible que las expresiones XPath sin prefijo no encuentren sus elementos; crea un XmlNamespaceManager y usa un prefijo en la consulta.
Leer XML como un flujo con System.Xml.XmlTextReader
System.Xml.XmlTextReader expone los nodos XML en el orden del documento mediante un lector de solo lectura y avance secuencial. No crea un árbol de documento completo, lo que puede reducir el uso de memoria con entradas grandes. Como el lector no permite retroceder, extrae cada valor cuando el nodo correspondiente aparece durante la lectura. Ciérralo en un bloque finally para liberar el identificador del archivo incluso si el procesamiento se interrumpe antes de terminar.
El siguiente ejemplo lee el atributo name de cada elemento de apertura Computer. Crea su propio archivo XML y libera el lector después de procesarlo.
$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 leer el texto de un elemento en lugar de un atributo, comprueba el nombre del elemento correspondiente y lee su texto cuando el lector esté situado en él. ReadString() lee el contenido de texto y hace avanzar el lector; ten en cuenta ese desplazamiento en bucles más complejos. Libera el lector al terminar: si lo dejas abierto, el archivo de entrada puede permanecer bloqueado.
Elegir un método de análisis de XML en PowerShell
Elige Select-Xml cuando una consulta XPath breve sea la forma más clara de recuperar unos pocos nodos de un archivo o una cadena. Elige System.Xml.XmlDocument si necesitas recorrer cómodamente el árbol, realizar varias consultas o acceder a nodos relacionados. Elige System.Xml.XmlTextReader si puedes procesar los nodos en orden y quieres evitar cargar un árbol completo en memoria.
Los tres métodos permiten leer elementos y atributos. La diferencia principal está en cómo presentan el documento: Select-Xml devuelve coincidencias XPath, XmlDocument permite recorrer un árbol cargado y XmlTextReader avanza por un flujo. Escoge el método que se ajuste al tamaño del documento y al tipo de consulta; después, comprueba si hay nodos o atributos opcionales cuando la entrada pueda omitirlos.