2 maneras de trabajar con XML desde PowerShell

Una de las frustraciones más grande con las que uno se encuentra al momento de iniciarse con PowerShell es la simple tarea de introducir y extraer (u obtener) datos. Por consecuente, si se desear avanzar en el camino de luz que PowerShell nos brinda, se debe saber trabajar con XML, ya que es un formato de intercambio de datos esencial y aún vigente para garantizar la preservación de los datos de un objeto. Eso sin contar que PowerShell siempre facilita las tareas…

Introducción al acceso de datos XML

Primeramente vamos a ver como importar archivos XML (porque hay varias formas de hacerlo) o generarlos directamente desde la consola a partir de nuestros datos.

Si aún no tienes muy claro como son los archivos XML, te recomiendo pasar por acá: Introduction to XML.

Vamos a partir de un documento ejemplo, es un poco viejo, pero sigue funcionando: Sample XML File (books.xml).

Ese contenido vamos a guardarlo y vamos a nombrarlo books.xml, para este post voy a dejar el archivo en la raíz de mi perfil.

Ya con el archivo listo el siguiente paso es obtener la información del mismo dentro de PowerShell, donde existen varios caminos para tal fin:

    # Método 1
    $xDoc = New-Object System.Xml.XmlDocument
    $file = Resolve-Path(".\books.xml")
    $xDoc.load($file)
    # Método 2
    [xml] $xDoc = Get-Content ".\books.xml"
    # Método 3
    $xDoc = [xml] (Get-Content ".\books.xml")

Fácil, no?

Ahoa veamos que nos devuelve al invocar la variable $xDoc, así como también un poco más de info al respecto:

Utilizando XPath

Con el archivo cargado en un objeto XmlDocument, es posible navegar por el árbol XML utilizando XPath. Para seleccionar un conjunto de nodos, use el método SelectNodes:

    $xdoc.SelectNodes("//author")

Donde el resultado es una lista de todos los autores disponibles. Pero hay un pequeño problema: existen repetidos. ¿Cómo sería la mejor manera de poder filtrar con los valores únicos? PowerShell tiene un cmdlet llamado Select-Xml, que permite realizar esto de la siguiente manera:

  $xdoc | Select-Xml "//author" | % { $_.Node.InnerText } | select -Unique

O también se encuentra a disposición SelectingleNode, para retornr un único nodo:

  #Toda la info del libro
  $xdoc.SelectSingleNode("//book[2]")
  #Solamente el título
  $xdoc.SelectSingleNode("//book[2]/title")

Accediendo a XML como Objetos

Siguiendo con el mismo objeto XmlDocument, PowerShell también proporciona compatibilidad con objetos dinámicos para datos del tipo XML: esto permite acceder a la información que el objeto XML contiene como objetos de PowerShell, que no requieren ni el selector XPath ni la necesidad de conocer en detalle los nodos XML ni sus valores. Por ejemplo desde VSCode y gracias a Intellisense, es posible acceder al esquema cuando se cargan los datos del archivo XML. El siguiente gif muestra en acción el proceso de obtención de opciones de selección y finalización de las palabras.

A continuación un par de ejemplos de cómo XML se convierte en objetos de PowerShell:

En donde también podemos acceder de forma individual a cada elemento (libro, en este caso) y sus respectivos datos:

Vale la pena destacar que todos los XML nodes del documento se convierten en propiedades de PowerShell, donde los valores de los elementos y los valores de los atributos se tratan exactamente de la misma manera: utilizando la notación de “punto” estándar.

Extra: Cambiar información

Para poder trabajar correctamente con el formato XML debemos tener en cuenta el procedimiento para actualizar valores, por ejemplo. Para ello el siguiente bloque de código ejemplifica el procedimiento para ello:

  $item = Select-XML -Xml $xDoc -XPath '//book[title="Midnight Rain"]'
  $item.Node
  $item.Node.price = 4.95
  $xDoc.Save(".\booksNewPrice.xml")

Donde al revisar el archivo anterior obtenemos el precio del libro actualizado, según nuestra modificación:

  Get-Content .\booksNewPrice.xml | Select-String "Midnight Rain" -Context 2,7

Happy scripting!

Comments