Ei, Equipe de Scripts!Perseguindo carros ... e XML

A Equipe de Scripts da Microsoft

Faça download do código deste artigo: HeyScriptingGuy2007_02.exe (150KB)

“NÃO SEI por que meu cachorro persegue carros” é a velha piada. “Afinal, o que ele faria se de fato conseguisse capturar um carro?”

Trata-se de uma boa pergunta que a Equipe de Scripts não consegue responder. Bem, a menos que quem capture o carro seja Lucy, a cadela lá da rua de baixo. Não temos dúvida nenhuma de que essa cadela roubaria uma loja de bebidas e depois usaria o carro para fugir. E, a julgar pelas condições do gramado da frente, estamos propensos a apostar que ela não se deteria em nenhuma pausa para descanso pelo caminho, se é que você me entende.

Se tivéssemos que atualizar essa piada antiga para a era atual de alta tecnologia, ficaria mais ou menos da seguinte forma: “Não sei por que meu administrador de sistemas continua tentando aprender XML. Afinal, o que ele faria se de fato conseguisse aprender?”

Observação Em nossa defesa, dissemos apenas que iríamos atualizar aquela piada antiga e ultrapassada, não dissemos em nenhum momento que a tornaríamos engraçada.

Para ser honesto, XML pode ser uma tecnologia um tanto quanto badalada, pelo menos quando se trata de administração de sistemas. A verdade é que muitos administradores de sistemas viveram por muito tempo e felizes sem ter que escrever um script sequer que interagisse com um arquivo XML, e não esperamos que isso mude em nenhum momento no futuro próximo.

Assim, é verdade também que cada vez mais aplicativos estão adotando o XML como padrão para armazenamento de dados. E por que não? Como não passam de arquivos de texto adornados, esses arquivos de dados XML são rápidos e fáceis de se criar, são portáteis em plataformas e não requerem nenhum programa de banco de dados complexo (e caro). Você tem um sistema operacional e um editor de texto? Então você pode criar um banco de dados XML.

O que significa, é claro, que existe pelo menos uma coisa o administrador de sistema possa fazer com o XML: escrever scripts que consultem um arquivo XML como se o arquivo fosse um banco de dados de pesquisa completo. E quem melhor que a Equipe de Scripts para dar algumas indicações de como fazer exatamente isto?

Tudo bem, boa observação. Mas, se tivéssemos fazer uma suposição, apostaríamos que Lucy provavelmente está muito ocupada cavando o canteiro de flores de alguém, para escrever uma coluna sobre XML.

Para começar, vamos dar uma olhada em um arquivo XML simples (veja a Figura 1), um arquivo de banco de dados destacando quatro scripts, encontrado na coluna diária Hey, Scripting Guy! !

Figure 1 Ei, Equipe de Scripts! Scripts em XML

<?xml version="1.0" encoding="ISO-8859-1"?>
<Repository>
  <Script>
    <Category>Microsoft Office</Category>
    <Subcategory>Microsoft Access</Subcategory>
    <Keyword>databases</Keyword>
    <Title>How Can I Print a Microsoft Access Report?</Title>
    <URL>http://www.microsoft.com/technet/scriptcenter/resources/qanda/oct06/hey1020.mspx</URL>
  </Script>
  <Script>
    <Category>Microsoft Office</Category>
    <Subcategory>Microsoft Access</Subcategory>
    <Keyword>databases</Keyword>
    <Title>How Can I Compact a Microsoft Access Database?</Title>
    <URL>http://www.microsoft.com/technet/scriptcenter/resources/qanda/oct06/hey1009.mspx</URL>
  </Script>
  <Script>
    <Category>Microsoft Office</Category>
    <Subcategory>Microsoft Word</Subcategory>
    <Keyword>hyperlinks</Keyword>
    <Title>How Can I Change an Existing Hyperlink in a Microsoft Word Document?</Title>
    <URL>http://www.microsoft.com/technet/scriptcenter/resources/qanda/oct06/hey1016.mspx</URL>
  </Script>
  <Script>
    <Category>Enterprise Servers</Category>
    <Subcategory>Microsoft SQL Server</Subcategory>
    <Keyword>databases</Keyword>
    <Title>How Can I Create a Table in a SQL Server Database?</Title>
    <URL>http://www.microsoft.com/technet/scriptcenter/resources/qanda/oct06/hey1016.mspx</URL>
  </Script>
</Repository>

Como você pode ver, trata-se de um arquivo pequeno e bem simples. Cada script individual é arquivado em uma marca <Script> . De agora em diante, vamos nos referir a esses scripts como registros. Sim, você tem razão - os aficionados por XML nunca se referem a esses itens como registros. Mas, tudo bem, nosso objetivo aqui é mostrar como aplicar algo que você já conhece: técnicas de consulta ao banco de dados, para um tipo novo e diferente de fonte de dados. Nós pensamos em nos concentrar primeiramente em como fazer as coisas, e depois, talvez, retornar a esse tópico no futuro e fornecer então a terminologia adequada.

OK, voltemos aos registros. Cada registro contém os seguintes campos: <Category>, <Subcategory>, <Keyword>, <Title>, and <URL>.

Hmm, você não está tão impressionado quanto pensamos que ficaria. Talvez ajudasse se tivéssemos mostrado a você um script que pudesse abrir esse arquivo XML e retornasse o conteúdo:

Set xmlDoc = CreateObject("Microsoft.XMLDOM")
xmlDoc.Async = "False"
xmlDoc.Load("C:\Scripts\Scripts.xml")

Set colNodes = xmlDoc.selectNodes _
("/Repository/Script/*")

For Each objNode in colNodes
   Wscript.Echo objNode.Text
Next

Observação tenha cuidado: esses nomes de marca fazem distinção entre maiúsculas e minúsculas. É “/Repository/Script" e não "/repository/script" ou "/REPOSITORY/SCRIPT".

Está certo, isso também não impressiona muito. Mas esta é a questão: isso não é nem de perto tão difícil quanto você possa esperar.

Como se pode observar no código, começamos criando uma instância do objeto Microsoft.XMLDOM, o objeto COM usado para trabalhar com arquivos XML. Depois, configuramos a propriedade Async para False; isso ajuda a assegurar que o arquivo inteiro seja lido na memória antes que o controle retorne para o script. Usamos em seguida o método Load para ler o arquivo C:\Scripts\Scripts.xml:

xmlDoc.Load("C:\Scripts\Scripts.xml")

Assim que o arquivo tiver sido carregado na memória, podemos usar o método selectNodes para selecionar o registro especificado no banco de dados:

Set colNodes = xmlDoc.selectNodes _
("/Repository/Script/*")

Examine de perto o parâmetro passado para selectNodes. Na verdade, ele representa o caminho no arquivo XML. Nosso arquivo XML tem esta estrutura:

<Repository>
    <Script>
        <Category></Category>
        <Subcategory></Subcategory>
        <Keyword></Keyword>
        <Title></Title>
        <URL></URL>
    </Script>
</Repository>

Você deve se importar com isso? Em poucas palavras, sim! Ao lidar com arquivos XML, a estrutura é muito importante. Por exemplo, como chegamos às propriedades individuais de um registro? É fácil: acessamos a marca <Repository>seguida pela marca <Script> e pelas marcas de propriedade individual. E...adivinhe só: É o mesmo caminho que especificamos como sendo o parâmetro para selectNodes. Simplesmente seguimos aquele caminho com /*, que significa "Selecione todas as propriedades para esses registros”. Em outras palavras, nossa coleção retornada consistirá em todas as propriedades de todos os registros do banco de dados - semelhante à consulta "Selecionar * De" do Windows® Management Instrumentation (WMI).

Observação dê uma chance ao script de exemplo e você verá exatamente o que queremos dizer.

O restante do script é fácil, tudo o que fazemos é configurar um loop For Each para percorrer a coleção, e retornarmos o valor da propriedade Text de cada item e cada propriedade:

For Each objNode in colNodes
   Wscript.Echo objNode.Text
Next

Muito mais fácil do que perseguir carros.

Mas, você está certo: se tudo o que desejávamos fazer era retornar o conteúdo inteiro do arquivo, poderíamos ter ignorado todos aqueles recursos XML e usado apenas o FileSystemObject. (Poderia ter sido um pouquinho mais complicado, mas só um pouquinho.) Se nossa intenção fosse deslumbrá-lo e fazê-lo pensar “Puxa, afinal esses recursos XML são muito úteis”, bem, provavelmente ainda temos maneiras de o fazer.

Então vejamos o que se pode fazer a respeito. No primeiro script obtivemos de volta todos os valores de propriedade de todos os registros. Tudo bem, mas, vamos supor que tudo o que realmente desejávamos ter de volta fosse o título do script? Isso é possível? Hmm, só um segundo...

OK, de acordo com Lucy, tudo o que devemos fazer é modificar o comando selectNodes, adicionando a propriedade de interesse ao final do caminho. Em outras palavras:

    Set colNodes=xmlDoc.selectNodes _    ("/Repository/Script/Title")

Acontece que o único motivo de termos obtido de volta todas as propriedades na primeira vez, é o fato de usamos o caractere curinga *. Agora obtivemos apenas a propriedade Title. Por quê? Porque esse é o único valor de propriedade que solicitamos de volta.

Observação Hmm, dê uma olhada nisto: O XML fornece exatamente o que você pede. Sem ofensas, Lucy, mas achamos que o XML é o novo melhor amigo do homem!

E, com certeza, é possível retornar mais de uma propriedade. Por exemplo, este comando modificado retorna valores para as propriedades Title e URL:

    Set colNodes=xmlDoc.selectNodes _    ("/Repository/Script/(Title | URL)")

Com certeza, a sintaxe tem uma aparência um tanto desajeitada, mas assim que você se acostuma a ela, não é tão ruim assim. Para começar, especificamos a parte principal do caminho, exatamente como fizemos anteriormente:

    /Repository/Script/

Em seguida, adicionamos um conjunto de parênteses e, dentro desses parênteses, especificamos as propriedades a serem retornadas. (Observe que usamos o separador pipe: o caractere | - para dividir as propriedades individuais). Ou seja:

    (Title | URL)

Como dissemos, talvez seja um pouco tolo, mas funciona.

E você não esta limitado a retornar apenas duas propriedades. Desde que você continue adicionando separadores pipe, poderá obter de volta todas as informações que desejar. Por exemplo, o comando a seguir retorna três propriedades (Title, URL e Keyword):

    Set colNodes=xmlDoc.selectNodes _    ("/Repository/Script/(Title | URL |          Keyword)")

Legal, hein?

Bem, nós achamos legal. Vocês são uma equipe corajosa. Mas, novamente, temos uma boa questão: tudo o que fizemos até aqui foi recuperar informações sobre todos os registros de nosso banco de dados. Entretanto, não há nada de errado nisso. Muitas vezes, isso é exatamente o que você deseja fazer. Por outro lado, também haverá momentos (muitos) em que desejaremos recuperar informações de apenas um subconjunto desses registros. Por exemplo, talvez desejemos obter de volta as informações apenas dos scripts que tenham uma palavra-chave igual aos bancos de dados. Você sabe, usando uma consulta semelhante a esta:

    Set colNodes=xmlDoc.selectNodes _
    ("/Repository/Script " & _
    "[Keyword = ‘databases’]")

Mais uma vez, a sintaxe é um pouco estranha. O lado bom é que, contudo, a sintaxe também é fácil e bem simples. Após especificar o caminho principal, colocamos nossa clausula "Where" (por exemplo, where x equals y) dentro de colchetes, assim:

/Repository/Script [Keyword = ‘databases’]

Como você provavelmente já deve ter entendido, nosso equivalente da cláusula Where informa ao script “Retornar apenas os itens onde o atributo Keyword for igual a database". Observe que database está entre aspas simples. Isso não é apenas perfeito, é praticamente necessário. Se o termo de filtragem estiver entre aspas duplas, você obterá um erro de sintaxe quando tentar executar o script.

Observação por quê? Porque, lembre-se, a seqüência de consulta inteira:"/Repository/Script [Keyword = ‘databases’]", está entre aspas duplas.

É claro que você não está limitado a usar o sinal de igual (=) quando filtrar os dados. Você poderá usar os sinais maior que (>) ou menor que (<), bem como os sinais favoritos de todos, menor que ou igual a (<=) e maior que ou igual a (>=). Você também pode negar qualquer um desses sinais, colocando um ponto de exclamação na frente. Por exemplo, este comando solicita todos os scripts quando a palavra-chave não for igual a database (observe o sinal !=):

    Set colNodes=xmlDoc.selectNodes _
    ("/Repository/Script " & _
    "[Keyword != ‘databases’]")

Espere um minuto: Quem foi que disse, "Claro, você pode configurar um filtro, mas aposto que você não pode configurar um filtro e especificar as propriedades que deseja retornar". Claro que você consegue:

    Set colNodes=xmlDoc.selectNodes _
    ("/Repository/Script " & _
    "[Keyword = ‘databases’]/Title")

Se tudo for bem,, esse comando retornará apenas a propriedade Title de todos os scripts que tenham bancos de dados Keyword. Vejamos se funciona:

    How Can I Print a Microsoft Access Report?
    How Can I Compact a Microsoft Access Database?
    How Can I Create a Table in a SQL Server     Database?

Vejamos se conseguimos ajustar mais um comando antes de irmos embora. Embora estejamos fazendo progressos, talvez ainda estejamos retornando mais registros do que queremos de fato retornar Afinal, nosso comando anterior retorna uma mistura de scripts do Microsoft ® Access® e scripts do Microsoft SQL Server™. (Por quê? Porque todos esses scripts usam os bancos de dados Keyword). E, se quiséssemos limitar os dados retornados a scripts que têm bancos de dados para uma palavra-chave e têm o Microsoft SQL Server™ como uma subcategoria? A filtragem com base em critérios múltiplos é possível?

Como se você tivesse que perguntar:

    Set colNodes=xmlDoc.selectNodes _
    ("/Repository/Script " & _
    "[Keyword = ‘databases’ and " & _
    "Subcategory = ‘Microsoft SQL Server’]")

É a mesma sintaxe básica, usamos apenas dois critérios separados (ou seja, palavra-chave = ‘database’ e Subcategoria = ‘Microsoft SQL Server’) e conectamos os dois, usando o operador AND.

Observação Sim, você têm razão: com esse arquivo XML pequeno e simples, bastava termos solicitado todos os scripts onde a Subcategoria fosse igual ao Microsoft SQL Server. Mas isso não teria graça nenhuma e não seria nem de perto educativo.

Você também pode usar as cláusulas OR. Por exemplo, suponhamos que tivéssemos um monte de scripts do Microsoft Office, incluindo scripts com Subcategorias iguais ao Microsoft Excel®, Microsoft PowerPoint®, Microsoft Outlook® e assim por diante. É possível restringir os dados retornados apenas aos scripts das subcategorias Microsoft Word ou Microsoft Acess? Pode apostar que sim:

    Set colNodes=xmlDoc.selectNodes _
    ("/Repository/Script " & _
    "[Subcategory = ‘Microsoft Word’ " & _
    "or Subcategory = ‘Microsoft Access’]")

É assim mesmo? Tudo bem, isso pode não ser qualificado como uma coluna que tenha mudado a sua vida para sempre, mas, ainda assim, existe uma boa chance de que, mais cedo ou mais tarde, a possibilidade de consultar um arquivo XML dessa maneira seja útil. Mas a decisão é sua: você pode aprender algumas técnicas de XML básicas ou perseguir carros. Você decide. (Se você escolher a última opção e acontecer de se encontrar com Lucy, a cadela da rua de baixo, diga a ela que a equipe dos Scripts manda um “Olá”. E diga a ela para ficar longe do nosso jardim!)

Ei, Equipe de Scripts! - Todos os dias

Você acabou de examinar a coluna Hey, Scripting Guy! deste mês e considerou este o melhor material técnico que já leu até hoje. Você poderia até ir além disso e afirmar que este é o melhor material escrito até hoje. Além disso, você já está ansiosamente aguardando, ao lado da caixa de correio, na expectativa da próxima edição da TechNet Magazine, só para poder ler mais artigos como este.

O que você está esperando então? Quer saber mais sobre a cadela da vizinhança ou ler sobre as explorações mais recentes do Scripting Son? Você ouviu como foi a partida de boliche Turducken no ano passado? Fique em dia com todos esses assuntos importantes, lendo a coluna diária (sim, dissemos diária): Ei, Equipe de Scripts (em inglês). . Sempre de segunda a sexta-feira (menos nos principais feriados e nas férias da Equipe de Scripts), você poderá ler tudo sobre o beisebol do curso secundário, o futebol americano e o basquete universitários e, vez por outra, ficar por dentro da previsão do tempo. (É verdade que só é local se "local" for Redmond para você, mas quem não deseja saber o que se passa com o clima em Redmond?)

E não é só isso, na verdade você aprenderá algo novo sobre script todos os dias. Sim, no meio de todo esse conteúdo instigante existem informações reais sobre scripts. Em cada coluna a Equipe de Scripts responde perguntas reais enviadas por quem eles presumem ser pessoas reais. Você pode ler a coluna diária online em microsoft.com/technet/scriptcenter/resources/qanda. Além disso, como eles já responderam centenas de perguntas, os arquivos são bem amplos e, sendo assim, representam uma grande fonte de informações de script (consulte microsoft.com/technet/scriptcenter/resources/qanda/hsgarch.mspx).

Você tem uma pergunta para a Equipe de Scripts? Você tem chances reduzidas de ter sua pergunta respondida, enviando-a para scripter@microsoft.com. (Por outro lado, você não terá chance nenhuma se não a enviar, sendo assim, o que você tem a perder? Ao contrário de um bilhete de loteria, é de graça e suas possibilidades são ligeiramente maiores).

A Equipe de Scripts da Microsoft trabalha para - bem, estão empregados por ela - a Microsoft. Quando não está jogando/treinando/assistindo beisebol (e diversas outras atividades), ela administra o TechNet Script Center. Confirme isso em www.scriptingguys.com (em inglês).

© 2008 Microsoft Corporation e CMP Media, LLC. Todos os direitos reservados. A reprodução parcial ou completa sem autorização é proibida..