¡Hola, encargados del scripting!¡Los juegos ya están en marcha! Ah, y también algo de XML

Los encargados del scripting

Descargar el código de este artículo: HeyScriptingGuy2008_02.exe (151KB)

¿Sabe?, cuando se habla de las leyendas del mundo deportivo, inevitablemente surgen siempre los mismos nombres: Babe Ruth. Pelé. Muhammad Ali. Walter Payton. ScooterK y MrRat. Johnny—

Ja, ja, ja, qué divertido... oh, ¿en serio? ¿Realmente no sabe quiénes son ScooterK y MrRat? Bien, para los que evidentemente no siguieron los Juegos de invierno de Scripting (del 15 de febrero al 3 de marzo en el TechNet Script Center, vaya a microsoft.com/technet/scriptcenter/funzone/games), ScooterK y MrRat son auténticas leyendas, competidores que consiguieron puntuaciones perfectas en al menos una división de los Juegos de invierno de Scripting 2007.

Y ahora viene lo bueno: ¿realmente espera ser una leyenda del fútbol como Pelé? Probablemente no. ¿Espera ser el campeón del mundo de boxeo de los pesos pesados? Bueno, parece que algunos encargados del scripting tienen dominado el tema del peso pesado, pero lo de ser campeones de boxeo parece que es algo más difícil de conseguir. Pero usted (sí, usted) se puede convertir fácilmente en el próximo ScooterK o MrRat.

Nota: en teoría, también pueda convertirse en el próximo Babe Ruth. Sólo tiene que poder comerse 24 perritos calientes entre dos juegos consecutivos de béisbol.

Calma. Le diremos cómo puede convertirse en el próximo ScooterK o MrRat (y tal vez en el próximo Bizzy o H2Data). Sólo tiene que presentarse en el Script Center y participar en los Juegos de Scripting. El 15 de febrero expondremos 10 eventos distintos (10 desafíos de scripting) y le retaremos a que los complete todos o alguno de ellos. Escriba un script que solucione el problema que proponemos y envíelo por correo electrónico a los encargados del scripting (encontrará todas las instrucciones en la página principal de Juegos de Scripting). Probaremos su script y, si funciona, conseguirá puntos. Realice correctamente los 10 eventos y también se convertirá en una leyenda del mundo deportivo. O al menos del mundo deportivo del scripting, que es prácticamente lo mismo.

Los Juegos de Scripting (del 15 de febrero al 3 de marzo) son divertidos y desafiantes. Y lo mejor de todo, los Juegos de Scripting son para todos. ¿Todavía no tiene mucha experiencia en scripting de administración de sistemas? Vaya a la división de principiantes. Tenemos competiciones independientes para principiantes en VBScript, Windows PowerShellTM y (novedad de este año) Perl. ¿Considera que la división de principiantes es un poco fácil? Entonces debe probar la división avanzada, que también tiene competiciones en VBScript, Windows PowerShell y Perl.

Los Juegos (¿hemos dicho que son del 15 de febrero al 3 de marzo?) son el acontecimiento de la temporada de scripting y no se los debe perder. Visite la página principal del Script Center para obtener sugerencias y trucos para preparar la competición y vuelva el 15 de febrero, fecha en que empezarán oficialmente los Juegos.

Del 15 de febrero al 3 de marzo. Por si lo había olvidado.

¿Cómo que qué es eso? Realmente estamos de acuerdo con usted: sacar una nueva columna ¡Hola, encargados del scripting! además del anuncio de los Juegos de Scripting probablemente suponga demasiadas emociones para un solo mes. Sin embargo, para tener contentas a las buenas personas de TechNet Magazine (ni qué decir tiene que es el objetivo principal de nuestras vidas), hemos decidido arriesgarnos y sacar una nueva columna de todos modos.

Hace exactamente un año (vaya, ¿ya ha pasado tanto tiempo?) publicamos una columna en la que se explicaba cómo usar un script para leer un archivo XML. Pero en esa columna no se explicaba cómo usar un script para crear, escribir y modificar un archivo XML. Este mes corregiremos esa injusticia. ¿Deseaba saber cómo escribir un script que pueda crear un archivo XML? Sólo tenía que preguntar. Bueno, preguntar y esperar un año a que tuviéramos tiempo para contestar. La Figura 1 muestra el script. Hay que reconocer que puede parecer complicado, pero explicaremos cómo funciona.

Figure 1 Crear un archivo XML

Set xmlDoc = _
  CreateObject("Microsoft.XMLDOM")  
  
Set objRoot = _
  xmlDoc.createElement("ITChecklist")  
xmlDoc.appendChild objRoot  

Set objRecord = _
  xmlDoc.createElement("ComputerAudit") 
objRoot.appendChild objRecord 
  
Set objName = _
  xmlDoc.createElement("ComputerName")  
objName.Text = "atl-ws-001"
objRecord.appendChild objName  

Set objDate = _
  xmlDoc.createElement("AuditDate")  
objDate.Text = Date  
objRecord.appendChild objDate  

Set objIntro = _
  xmlDoc.createProcessingInstruction _
  ("xml","version='1.0'")  
xmlDoc.insertBefore _
  objIntro,xmlDoc.childNodes(0)  

xmlDoc.Save "C:\Scripts\Audits.xml"  

Para empezar, creamos una instancia del objeto Microsoft.XMLDOM. Tal y como habrá adivinado, se trata del objeto que nos permite trabajar con archivos XML. Nuestro objetivo es crear un archivo XML simple similar al de la Figura 2.

Figura 2 Nuestro destino: un archivo XML simple

Figura 2** Nuestro destino: un archivo XML simple **

Para crear este archivo XML, lo primero que necesitamos hacer es crear el nodo raíz (ITChecklist). ¿Cómo lo hacemos? Así:

Set objRoot = _
  xmlDoc.createElement("ITChecklist")  
xmlDoc.appendChild objRoot  

Bastante fácil, ¿verdad? Sólo había que llamar al método createElement y pasarle el nombre que deseamos asignar al nodo raíz. Después llamamos al método appendChild y le pasamos la referencia de objeto a nuestro nuevo elemento (objRoot) como el único parámetro de método. En este momento ya tenemos un nodo raíz.

Pero, espere, hay más. A continuación creamos el nodo ComputerAudit, un nodo secundario del nodo ITChecklist que representa la información de un solo equipo. Como puede ver, el código para crear este nodo es similar al empleado para crear el nodo raíz:

Set objRecord = _
  xmlDoc.createElement("ComputerAudit") 
objRoot.appendChild objRecord 

La única diferencia es ésta: cuando creamos el nodo raíz, llamamos a appendChild en nuestro documento XML (observe la referencia de objeto xmlDoc). Para agregar un nuevo nodo secundario a la raíz, llamamos a appendChild en el nodo raíz (objRoot) en lugar del documento XML. Así de sencillo.

Igualmente sencillo resulta agregar los nodos ComputerName y AuditDate como nodos secundarios de ComputerAudit. Para ello, realizaremos un proceso similar: vamos a llamar a createElement para crear un nuevo nodo y llamaremos a appendChild para anexar este nuevo nodo al archivo.

Pregunta rápida: ¿desde dónde llamamos a appendChild esta vez? Correcto: desde objRecord, el nodo primario (ComputerAudit) que acabamos de crear.

Ah, y como los nodos ComputerName y AuditDate deben contener valores, es importante que también especifiquemos un valor para la propiedad Text de cada uno de estos nodos antes de que los agreguemos al documento.

Todo se aclarará cuando examinemos el código que realmente crea el nodo ComputerName:

Set objName = _
  xmlDoc.createElement("ComputerName")  
objName.Text = "atl-ws-001"
objRecord.appendChild objName  

Como es de esperar, el código para crear AuditDate es prácticamente idéntico. Sólo tenemos que especificar un nombre de nodo distinto al llamar a createElement y asignar un valor diferente a la propiedad Text.

Vaya, lo estamos poniendo fácil para todos, ¿no le parece?

Después de finalizar la creación de los nodos de nuestro primer (y en este caso, único) registro, ejecutamos este encantador bloque de código:

Set objIntro = _
 xmlDoc.createProcessingInstruction _
  ("xml","version='1.0'")  
xmlDoc.insertBefore _
  objIntro,xmlDoc.childNodes(0)  

Esto simplemente inserta la etiqueta <?xml version="1.0" ?> al principio del archivo, lo que garantiza que tenemos un documento XML con el formato correcto.

Ahora, lo que nos queda por hacer es llamar al método Save y guardar nuestro nuevo archivo como C:\Scripts\Audits.xml:

xmlDoc.Save "C:\Scripts\Audits.xml"  

De esta manera, obtenemos un documento XML completamente nuevo.

Realmente resulta útil: ahora ya sabe crear un archivo XML completamente nuevo con un script. Evidentemente, lo más probable es que la mayor parte del tiempo no necesite realmente crear un archivo XML totalmente nuevo, sino que deba anexar nuevos datos a un archivo existente. ¿Los encargados del scripting enseñarán cómo se hace?

Bueno, en un principio decidimos que la respuesta a esa pregunta era No, que no enseñaríamos a anexar datos a un archivo XML existente. Pero como somos buenos y generosos, decidimos intentar llegar a un acuerdo con los lectores de TechNet Magazine: si todos los que están leyendo esta revista aceptan participar en los Juegos de invierno de Scripting 2008, como compensación les enseñaríamos a usar un script para anexar datos a un archivo XML. Así pues, ¿todos están de acuerdo en participar en los Juegos de Scripting?

Eh, le estamos esperando. Sí, usted, el de Rochester, Massachussets.

Eso es, mejor así. Y, de verdad, se divertirá en los Juegos de Scripting. Todo el mundo se divierte. Lo prometemos.

Y como un trato es un trato, le mostraremos un script que puede anexar datos a un archivo XML existente. Eche un vistazo a la Figura 3.

Figure 3 Anexar a un archivo XML

Set xmlDoc = _
  CreateObject("Microsoft.XMLDOM")

xmlDoc.Async = "False"
xmlDoc.Load("C:\Scripts\Audits.xml")

Set objRoot = xmlDoc.documentElement
  
Set objRecord = _
  xmlDoc.createElement("ComputerAudit")
objRoot.appendChild objRecord

Set objFieldValue = _
  xmlDoc.createElement("ComputerName")
objFieldValue.Text = "atl-ws-100"
objRecord.appendChild objFieldValue

Set objFieldValue = _
  xmlDoc.createElement("AuditDate")
objFieldValue.Text = Date
objRecord.appendChild objFieldValue
  
xmlDoc.Save "C:\Scripts\Audits.xml"  

Como puede ver, no es demasiado distinto del script que creaba el archivo XML. Empezamos con la creación de una instancia del objeto Microsoft.XMLDOM, a continuación la propiedad Async se establece en False, lo que indica al script que deseamos cargar el documento sincrónicamente en vez de hacerlo asincrónicamente. ¿Cuál es la diferencia? Bueno, si cargamos el documento asincrónicamente, el script continuaría libremente aunque no se hubiera cargado el documento por completo. Ni qué decir tiene los problemas que se producirían al instante si se intenta realizar una tarea en un documento que todavía no existe. Al asegurarnos de que nuestro archivo XML se carga asincrónicamente también garantizamos que el archivo estará totalmente cargado antes de que continúe el script.

Y hablando de totalmente cargado... bueno, no importa; lo dejaremos pasar. En su lugar, llamamos al método Load para abrir el archivo C:\Scripts\Audits.xml. Tan pronto como se abre el archivo, usamos esta línea de código para crear una instancia de la clase documentElement, que tiene el resultado final de enlazarnos a la raíz del documento. En este caso, por supuesto, es el nodo ITChecklist:

Set objRoot = xmlDoc.documentElement

A partir de ahí, todo es cuesta abajo. Creamos una nueva instancia del nodo ComputerAudit con el método appendChild para agregar el nuevo nodo al archivo. Después creamos nuevas instancias de los nodos ComputerName y AuditDate, especificando los valores adecuados (atl-ws-100 y la fecha actual, respectivamente) para cada nodo nuevo. Guardamos estos dos elementos en el nuevo nodo ComputerAudit que acabamos de crear, llamamos al método Save para guardar el archivo y volvemos alegremente a trabajar en nuestros scripts para los próximos Juegos de Scripting.

Que, por si no lo hemos dicho, serán del 15 de febrero al 3 de marzo en el TechNet Script Center.

Ningún problema por el momento. Podemos crear un nuevo archivo XML y agregar nuevos registros a ese archivo. Todo eso está muy bien, pero todavía faltan cosas, por ejemplo, ¿cómo modificamos los registros existentes del archivo? Bien, al menos hay una forma de hacerlo, tal y como se muestra en la Figura 4.

Figure 4 Modificar el XML

Set xmlDoc = _
  CreateObject("Microsoft.XMLDOM")

xmlDoc.Async = "False"
xmlDoc.Load("C:\Scripts\Audits.xml")

Set colNodes=xmlDoc.selectNodes _
  ("/ITChecklist/ComputerAudit " & _
   "[ComputerName = 'atl-ws-100']/AuditDate")

For Each objNode in colNodes
   objNode.Text = Date
Next
  
xmlDoc.Save "C:\Scripts\Audits.xml"  

La parte importante de este script se produce cuando llamamos al método selectNodes, un método que determina los registros que devolverá nuestra consulta. Como puede ver, cuando llamamos a selectNodes tenemos cuidado de especificar dos criterios: sólo deseamos los registros en los que el atributo ComputerName sea igual a atl-ws-100 y que sólo se devuelva el atributo AuditDate.

Nota: ¿que no entiende cómo funciona? Eche un vistazo a nuestro primer artículo acerca del trabajo con archivos XML (technetmagazine.com/issues/2007/02/HeyScriptingGuy). En él se explica la sintaxis de consulta de selectNodes con más detalle.

Como es habitual, selectNodes devuelve una colección de todos los registros XML que cumplen los criterios especificados. A su vez, esto significa que podemos actualizar el valor del atributo AuditDate (el único atributo que hemos solicitado), con tan sólo configurar un bucle For Each para recorrer todos los elementos de la colección y, a continuación, en dicho bucle asignar un nuevo valor a AuditDate:

For Each objNode in colNodes
   objNode.Text = Date
Next

¿Que qué es eso? ¿Se pregunta si podemos modificar varios atributos a la vez? Sí, es posible. Pero, lamentablemente, hoy no. Es algo que tendremos que tratar en una columna futura.

Tiene otra pregunta: ¿cómo se actualiza la fecha de auditoría de todos los equipos del archivo? La respuesta es fácil: use el script de la Figura 5.

Figure 5 Cambiar la fecha de la auditoría

Set xmlDoc = _
  CreateObject("Microsoft.XMLDOM")

xmlDoc.Async = "False"
xmlDoc.Load("C:\Scripts\Audits.xml")

Set colNodes=xmlDoc.selectNodes _
  ("/ITChecklist/ComputerAudit/AuditDate")

For Each objNode in colNodes
   objNode.Text = Date
Next
  
xmlDoc.Save "C:\Scripts\Audits.xml"

¿Cuál es la única diferencia entre este script y nuestro script anterior para modificar XML? Con éste no se especifica que sólo deseamos ver los registros en los que ComputerName es igual a atl-ws-100. Si se omite ese criterio, se obtienen todos los registros de forma predeterminada.

Veamos un último script antes de acabar. Supongamos que nuestro viejo colega atl-ws-100 ha jugado su última partida de solitario y que se ha ido al cielo informático.

Nota teológica: ¿a dónde van los equipos cuando se mueren? Resulta que normalmente se entregan a uno de los encargados del scripting. Por ejemplo, al encargado del scripting que escribe esta columna le regalaron una vez un equipo portátil porque "has hecho mucho en favor de Microsoft y realmente te mereces un equipo portátil". El único inconveniente de este regalo generoso es que el equipo estaba roto y no se podía encender. Lo que probablemente fue lo mejor. Tampoco tenía disco duro.

Para cerrar el gran círculo de la vida del silicio, debemos eliminar atl-ws-100 de nuestro archivo XML. ¿Cómo lo vamos a hacer? Consulte la Figura 6.

Figure 6 Eliminar del archivo XML

Set xmlDoc = _
  CreateObject("Microsoft.XMLDOM")

xmlDoc.Async = "False"
xmlDoc.Load("C:\Scripts\Audits.xml")

Set colNodes=xmlDoc.selectNodes _
  ("/ITChecklist/ComputerAudit " & _
   "[ComputerName = 'atl-ws-100']")

For Each objNode in colNodes
  xmlDoc.documentElement.removeChild _
    (objNode)
Next
  
xmlDoc.Save "C:\Scripts\Audits.xml"  

Como puede ver, se parece a nuestro script anterior, el que modificaba la propiedad AuditDate. Realmente sólo hay dos diferencias. Por un lado, observe que no nos hemos molestado en especificar valores de propiedad en nuestra consulta de selectNodes. Cuando los especificamos, obtenemos el registro XML completo para atl-ws-100:

Set colNodes=xmlDoc.selectNodes _
  ("/ITChecklist/ComputerAudit " & _
   "[ComputerName = 'atl-ws-100']")

Y, después, en cada bucle For Each llamamos al método removeChild para eliminar todos los registros en los que ComputerName sea igual a atl-ws-100:

xmlDoc.documentElement.removeChild _
  (objNode)

Y eso es todo. Adiós, atl-ws-100; apenas te llegamos a conocer.

Vale, ¿algún editor de TechNet Magazine sigue leyendo la columna de este mes? ¿Se han ido todos a probar el rompecabezas de scripting mensual? Excelente. Ahora que no hay nadie vigilándonos, le vamos a decir una cosa: deje todo lo que esté haciendo (por ejemplo, leer esta revista) y vaya al Script Center y empiece a prepararse para los Juegos de Scripting. Después de todo, TechNet Magazine seguirá aquí mucho tiempo. Pero los Juegos de Scripting sólo ocurren una vez al año y durante un tiempo limitado (en concreto, del 15 de febrero al 3 de marzo, como ya debe saber). ¡No se lo pierda!

Nota: ¿sabe?, ahora que lo menciona, hemos esperado a que lea toda nuestra columna antes de decirle que deje de leer TechNet Magazine, ¿verdad? Cómo habrá podido suceder...

Dr. Scripto's Scripting Perplexer

El desafío mensual que pone a prueba no sólo sus habilidades para resolver rompecabezas sino también sus habilidades de scripting.

Febrero de 2008: Símbolos misteriosos

El teclado del equipo incluye todo tipo de caracteres de aspecto chiflado, pero más chiflado aún es el hecho de que la mayoría de estos caracteres tengan un uso específico en los lenguajes de scripting VBScript o Windows PowerShell. Vea si puede enlazar cada símbolo con su uso de scripting. Ya ha hecho el primero.

ANSWER:

Dr. Scripto's Scripting Perplexer

Respuesta: Símbolos misteriosos, febrero de 2008

  

Los encargados del scripting trabajan para Microsoft, mejor dicho, están contratados por Microsoft. Cuando no juegan/entrenan/ven béisbol (u otras actividades varias), dirigen el TechNet Script Center. Visite la página web en www.scriptingguys.com.

© 2008 Microsoft Corporation and CMP Media, LLC. Reservados todos los derechos; queda prohibida la reproducción parcial o total sin previa autorización.