Este artigo foi traduzido por máquina.

Windows PowerShell

Crie Interfaces XML amigáveis com o Windows PowerShell

Joe Leibowitz

Baixar o código de exemplo

A linguagem de script do Windows PowerShell faz tudo o que você quer uma ferramenta de linha de comando para fazer — e muito mais — que ele poderia eventualmente substituir tecnologias como VBScript. Para uma boa descrição geral do que se trata do Windows PowerShell e o básico de usá-lo, consulte bit.ly/LE4SU6 e bit.ly/eBucBI.

O Windows PowerShell é completamente integrado com o Microsoft .net Framework e, portanto, está profundamente ligado ao XML, o atual padrão internacional para troca de dados usando arquivos de texto estruturado. Para obter informações gerais sobre XML, consulte bit.ly/JHfzw.

Este artigo explora a capacidade do Windows PowerShell para apresentar e manipular dados XML com o objetivo de criar uma interface de usuário relativamente simple para leitura e edição de arquivos XML. A idéia é tornar isso mais fácil e conveniente usando algoritmos que "entendem" as relações pai-filho e irmão de qualquer arquivo dado, mesmo sem conhecimento prévio do esquema. Também vou examinar o uso dos formulários do Windows no Windows PowerShell, a consulta de XPath e outras tecnologias relacionadas. O app proposto pode digerir um arquivo XML e emitir consultas XPath no seus próprios.

Vejamos como você pode analisar qualquer arquivo XML no Windows PowerShell e apresentá-lo em um formato que as pessoas sem conhecimentos técnicos avançados podem usar. Figura 1 mostra uma visualização do tipo de GUI, você pode criar.

Preliminary View of the GUI
Figura 1 vista preliminar do GUI

A chave para fazer isso acontecer é para permitir a aplicação de Windows Power Shell analisar e compreender qualquer arquivo XML sem orientação humana ou da presciência de seu esquema. Depois de Pesquisar as tecnologias existentes para a análise automatizada de arquivos XML, decidi desenvolver um mecanismo de análise para esta finalidade específica, porque o que eu era capaz de encontrar não resolver completamente a necessidade de compreender os documentos XML sem a visão humana. Atualmente, aplicações universalmente parecem assumir que um desenvolvedor ou usuário é bem-familiares com os elementos, atributos e esquema geral de qualquer determinado documento XML. Mas alguns — possivelmente muitos — situações do mundo real não se enquadram nesse paradigma. Por exemplo, em um cenário com muitos consumidores de dados que não são especialistas em XML, mas que precisam de acesso a uma variedade de fontes de dados XML, a familiaridade do paradigma existente falha de pressuposição. Da mesma forma, mesmo com um especialista treinado ou dois com o pessoal, se uma organização enfrenta centenas ou milhares de arquivos XML estruturados de forma diferente, manipulação humana poderia facilmente tornar-se oprimido.

Portanto, o que é necessário é um mecanismo de análise que vai ler qualquer arquivo XML e emitir XPaths que usuários comuns, com apenas um mínimo de treinamento, podem usar para pesquisar e editar qualquer arquivo XML fornecido.

O mecanismo de análise de XML

Para ser compatível com XML, devem corresponder a de um documento fechamento e colchetes de abertura. Por exemplo, se um elemento <ABC> existe, também deve existir em algum momento posterior no mesmo arquivo de um elemento </ABC>. Entre estes de abertura e colchetes de fechamento, quase nada pode teoricamente ocorrer. Usando este princípio fundamental do XML, mostrarei como construir automaticamente uma série abrangente de consultas XPath que consumidores de dados XML ainda relativamente inexperientes rapidamente podem colocá-los a usar para encontrar e manipular dados em arquivos XML.

Em primeiro lugar, estabelece um conjunto de matrizes para armazenar todos abrindo e fechando os colchetes no arquivo XML:

[int[]]$leading_brackets = @()
[int[]]$closing_brackets = @()
[string[]]$leading_value = @()
[string[]]$closing_value = @()

Para construir uma matriz de rigidez de tamanho desconhecido no Windows PowerShell, três elementos são necessários: o [tipo []], levando a parte; uma parte do nome de $; e o símbolo para uma matriz de tamanho desconhecido, @ (). Variáveis no Windows PowerShell tomam $ como seu personagem principal. Essas matrizes particulares cobrem as localizações indexadas de abertura e fechamento de colchetes angulares no documento XML, bem como os valores de seqüência de caracteres dos nomes de elemento associados com estes suportes. Por exemplo, no XML linha o valor de texto de <PS1> </PS1>, o índice inteiro dos suportes principais seria 0 e o índice de colchetes de fechamento seria 15. O líder e os valores de fechamento neste caso seria PS1.

Para obter nosso destino XML em memória, usamos o seguinte código:

 

$xdoc = New-Object System.Xml.XmlDocument
       $xdoc.Load("C:\temp\XMLSample.xml")

Figura 2 é uma visão parcial do arquivo XML real que está sendo usado.

Figura 2 Vista parcial do arquivo XML de exemplo

<?xml version="1.0" encoding="utf-8"?>
<Sciences>
  <Chemistry>
    <Organic ID="C1" origination="Ancient Greece" age="2800 yrs">
      <branch ID="C1a">
        <size>300</size>
        <price>1000</price>
        <degree>easy&gt;</degree>
        <origin>Athens</origin>
        // Text for organic chem here
      </branch>
      <branch name="early" ID="C1b" source="Egypt" number="14">
        <size>100</size>
        <price>3000</price>
        <degree>hard&gt;</degree>
        <origin>Alexandria</origin>
        // Text for original Egyptian science
      </branch>
    </Organic>
  </Chemistry>
<Physics></Physics>
<Biology ID="B" origination="17th century" >
.
.
.
<Trees4a name="trees4a" age="40000000">
        <type ID="Tda1">oakda</type>
        <type ID="Tda2">elmda</type>
        <type ID="Tda3">oakd3a</type>
      </Trees4a>
    </Plants>
  </Biology>
</Sciences>

Após a operação de carga, estes dados XML são na memória. A fim de manipular e analisar XML, eu uso o modelo de objeto do documento agora é instanciado na variável $ xDoc. (mas eu também vou precisar usar a tecnologia de XPathNavigator para alguns fins específicos, como observado neste artigo):

# Create an XPath navigator (comments in PowerShell code take the \"#\" leading character)
$nav = $xdoc.CreateNavigator()

Uma das características mais interessantes do Windows PowerShell é a função interna ou o cmdlet chamado Get-Member, que permite que você examine os métodos e propriedades de qualquer objeto no Windows PowerShell direito no IDE, como você desenvolve. Figura 3 inclui uma chamada para esse cmdlet no objeto nav $ apenas criado, e Figura 4 mostra os resultados exibidos no Windows PowerShell integrada Scripting Environment (ISE), quando é feita a chamada de Get-Help.

Figura 3 resultados de chamada de Get-Member

Get-Member -InputObject $nav
                      TypeName: System.Xml.DocumentXPathNavigator
Name                 MemberType Definition
----                 ---------- ----------
AppendChild          Method     System.Xml.XmlWriter AppendChild(), System.V...
AppendChildElement   Method     System.Void AppendChildElement(string prefix...
CheckValidity        Method     bool CheckValidity(System.Xml.Schema.XmlSche...
Clone                Method     System.Xml.XPath.XPathNavigator Clone()
ComparePosition      Method     System.Xml.XmlNodeOrder ComparePosition(Syst...
Compile              Method     System.Xml.XPath.XPathExpression Compile(str...
CreateAttribute      Method     System.Void CreateAttribute(string prefix, s...
CreateAttributes     Method     System.Xml.XmlWriter CreateAttributes()
CreateNavigator      Method     System.Xml.XPath.XPathNavigator CreateNaviga...
DeleteRange          Method     System.Void DeleteRange(System.Xml.XPath.XPa...
DeleteSelf           Method     System.Void DeleteSelf()
Equals               Method     bool Equals(System.Object obj)
Evaluate             Method     System.Object Evaluate(string xpath), System...
GetAttribute         Method     string GetAttribute(string localName, string...
GetHashCode          Method     int GetHashCode()
TypeName: System.Xml.DocumentXPathNavigator
.
.
.
.
.
Value                Property   System.String Value {get;}
ValueAsBoolean       Property   System.Boolean ValueAsBoolean {get;}
ValueAsDateTime      Property   System.DateTime ValueAsDateTime {get;}
ValueAsDouble        Property   System.Double ValueAsDouble {get;}
ValueAsInt           Property   System.Int32 ValueAsInt {get;}
ValueAsLong          Property   System.Int64 ValueAsLong {get;}
ValueType            Property   System.Type ValueType {get;}
XmlLang              Property   System.String XmlLang {get;}
XmlType              Property   System.Xml.Schema.XmlSchemaType XmlType {get;}

Results of Get-Help in Windows PowerShell
Figura 4 resultados de Get-Help no Windows PowerShell

Enquanto Get-Member, frequentemente, vai colocá-lo no caminho certo durante o desenvolvimento do Windows PowerShell, você também encontrará o cmdlet Get-Help associado à mão durante este processo.

Se você digitar get-help xml na linha de comando, como mostrado na Figura 4, você terá a saída mostrada abaixo:

getName                 Category  Synopsis
----                 --------  --------
Export-Clixml        Cmdlet    Creates an XML-based representation of an object or...
Import-Clixml        Cmdlet    Imports a CLIXML file and creates corresponding obj...
ConvertTo-XML        Cmdlet    Creates an XML-based representation of an object.     
Select-XML           Cmdlet    Finds text in an XML string or document.             
about_format.ps1xml  HelpFile  The Format.ps1xml files in Windows PowerShell defin...
about_types.ps1xml   HelpFile  Explains how the Types.ps1xml files let you extend ...

Se você digitar get-help about_types, você verá os resultados mostrados na Figura 5.

Figura 5 Obtendo ajuda com arquivos ps1xml

TOPIC
    about_Types.ps1xml
SHORT DESCRIPTION
    Explains how the Types.ps1xml files let you extend the Microsoft .NET Framework types of the objects that are used in Windows PowerShell.
LONG DESCRIPTION
    The Types.ps1xml file in the Windows PowerShell installation directory ($pshome) is an XML-based text file that lets you add properties and methods to the objects that are used in Windows PowerShell.
Windows PowerShell has a built-in Types.ps1xml file that adds several elements to the .NET Framework types, but you can create additional Types.ps1xml files to further extend the types.
SEE ALSO
    about_Signing
    Copy-Item
    Get-Member
    Update-TypeData

O sistema de Windows PowerShell integrada para Pesquisar sintaxe é abrangente e relativamente fácil de usar. Este é um tópico que merece seu próprio artigo.

Para obter o XML em condição de análise prontos, use o método Select do XpathNavigator:

$nav.Select("/") | % { $ouxml = $_.OuterXml }

Na primeira parte desta declaração, invoco.Selecione a consulta XPath simple "/", dando todo o conteúdo do XML. Na segunda parte, após o símbolo do Windows PowerShell | de seu pipeline de objeto, fazer um foreach, representado pelo alias %; Eu poderia ter usado foreach, em vez de alias. Dentro do loop, construir o trabalho XML string dados variável $ouxml da.Propriedade OuterXML dos objetos sendo processados no loop. Voltando à Figura 3,.OuterXML é uma das propriedades do objeto XPathNavigator. Essa propriedade fornece um conjunto completo de todos os suportes de ângulo no arquivo XML, que é necessário para o motor de análise funcionar corretamente.

Observe que, para objetos indo através de um gasoduto, $_ é o símbolo para a instância especial, com a notação de ponto usada para obter os métodos e propriedades de cada instância. Cada objeto no pipeline é dirigido ou referenciados usando o símbolo de _ $.  Para obter um atributo do objeto _ $, use, por exemplo, $_.Nome (se o nome é uma propriedade de membro do objeto específico). Tudo passando através de um gasoduto de Windows PowerShell é um objeto com propriedades e métodos.

Uma última etapa de preparação antes de analisar a "regularizar" o texto XML, tratando qualquer especial casos que parecem <ShortNode/>. O mecanismo de análise prefiro ver as mesmas informações em um formato diferente: <ShortNode> </ShortNode>. O código a seguir inicia esta transformação usando uma RegEx e olhando para os jogos:

$ms = $ouxml | select-string -pattern "<([a-zA-Z0-9]*)\b[^>]*/>"   -allmatches
foreach($m in $ms.Matches){ ‘regularize’ to the longer format }

Você pode agora olhar o código analítico principal para este aplicativo: o mecanismo de análise que irá preencher as quatro matrizes listadas anteriormente. Figura 6 mostra o código que testa o arquivo para abrir colchetes.

Figura 6 testar um arquivo para abrir colchetes

# if you run out of “<” you’re done, so use the “$found_bracket” Boolean variable to test for presence of “<”
$found_bracket = $true
while($found_bracket -eq $true)
{
  # Special case of first, or root element, of the XML document;
  # here the script-level variable $ctr equals zero.
if($Script:ctr -eq 0)
    {
    #to handle the top-level root
    $leading_brackets += $ouxml.IndexOf("<",$leading_brackets[$Script:ctr])
    $leading_value += $ouxml.Substring(0,$ind)
    $closing_brackets += $ouxml.IndexOf("</" + $leading_value[0].Substring(1))
    $Script:ctr+=1
    }
}

O código em Figura 6 manipula o caso especial do elemento raiz do documento XML. Outra regra fundamental do XML é que cada esquema deve conter um único conjunto de raiz global de colchetes; dentro destes símbolos de delimitador, os dados XML podem ser estruturados de forma coerente com a regra de correspondência mencionada anteriormente, ou seja, para cada "<ABC>" lá um "< / ABC."

Observe que a sintaxe + = é usada para adicionar um item ou elemento de uma matriz. Mais tarde, após ser preenchido com elementos, como uma matriz pode ser acessada através de indexação, como em $leading_brackets [3].

Os argumentos de IndexOf, observe que a posição inicial para a pesquisa, representada pelo segundo parâmetro do método, mostra uma referência de Script $: ctr. No Windows PowerShell, variáveis têm escopos distintos que se seguem, a partir de onde eles são criados. Porque a variável $ctr aqui é criado fora do escopo de qualquer função, ele é considerado o nível de script e uma variável de nível de script não pode ser alterada dentro de uma função sem se referir a $Script. Dentro de um loop, ao invés de dentro de uma função, a referência de Script $ não pode ser exigida, mas é um bom hábito de manter o escopo na mente em todos os tempos.

Durante a codificação, uma boa dica para uma violação de escopo é uma variável que deve estar mudando no valor, mas não é; Geralmente, isso é porque ele está fora do escopo e precisa ser prefixados em conformidade.

Uma vez que o elemento raiz é tratado, todos os outros elementos são manipulados dentro de um bloco else:

else
{
# Check for more \"<\"
$check = $ouxml.IndexOf("<",$leading_brackets[$Script:ctr-1]+1)
if($check -eq - 1)
{
break
}

A primeira coisa a fazer é verificar se o final do arquivo foi atingido; o critério para que o evento é a ausência de mais < símbolos. O código anterior faz isso. Se não existem mais < símbolos, uma pausa é chamada.

O seguinte segmento de código distingue entre < casos e < / casos:

#eliminate "</" cases of "<"
if($ouxml.IndexOf("</",$leading_brackets[$Script:ctr-1]+1) -ne `
  $ouxml.IndexOf("<",$leading_brackets[$Script:ctr-1]+1))

Porque você está tentando acumular todos os suportes de ângulo de abertura, você quer saber apenas sobre estas nesta fase de análise de operações de motor. Observe a sintaxe do Windows PowerShell para "não igual" em comparações: -ne. Relacionadas com operadores incluem - eq,-lt e - gt. Também, como no Visual Basic (mas ao contrário de C#), você precisa de um caractere de quebra automática de linha, o símbolo de volta-escala ('), para continuar uma linha de código.

Se o teste for bem-sucedido, preencha a matriz de leading_brackets $ com um novo elemento:

$leading_brackets += $ouxml.IndexOf("<",$leading_brackets[$Script:ctr-1]+1)

Com a mais recente iteração de colchetes líderes estabelecido, a tarefa seguinte é isolar o nome do elemento associado. Para essa tarefa, observe que após a abertura inicial < e o nome do elemento < ElementName, há em ambos um espaço seguido por um ou mais atributos, ou os suportes de fechar, como nos seguintes casos:

<ElementName attribute1="X" attribute2 = "Y">, or
<ElementName>

Separar estes dois casos com o seguinte código, que olha para ver o que vem em primeiro lugar, um espaço ou o > símbolo:

$indx_space = $ouxml.IndexOf(" ",$leading_brackets[$Script:ctr])
  $indx_close = $ouxml.IndexOf(">",$leading_brackets[$Script:ctr])
  if($indx_space -lt $indx_close)
  {
  $indx_to_use = $indx_space
  }
  else
  {
  $indx_to_use = $indx_close
  }

Uma vez que você estabelecer o ponto final adequado, empregam $indx_to_use para ajudar a isolar a cadeia associada com o colchete angular líder que agora está em foco:

$leading_value += $ouxml.Substring($leading_brackets[$Script:ctr],($indx_to_use -
  $leading_brackets[$Script:ctr]))

Com efeito, o principal valor é a seqüência de caracteres começando com < e terminando com um um espaço ou um >.

O palco está montado para pegar o correlativo colchetes de fechamento por encontrar a seqüência de caracteres < / ElementName:

$closing_brackets += $ouxml.IndexOf("</" + $leading_value[$Script:ctr].Substring(1),`
  $leading_brackets[$Script:ctr]+1)
$Script:ctr+=1

Finalmente, no caso a distinção entre < e < / não é atendidas, incrementar o elemento de matriz e continuar:

else
{
$leading_brackets[$Script:ctr-1] +=1
}

No final deste processo, as três matrizes parecem com a seguinte apresentação parcial de seus dados:

$leading_brackets:
0 18 62 109 179 207 241 360 375 447 475 509 625 639 681 713 741 775 808 844 900 915 948 976 1012 1044 1077 1142 1154 1203 1292 1329 1344 1426 1475 1490 1616 1687 1701 1743 1810 1842 1890 1904 1941 1979 2031 2046 2085 2138 2153 2186 2235 2250 2315 2362 2378 2442 2476 2524 2539 2607 2643 2718
$leading_value:
<Sciences <Chemistry <Organic <branch <size <price <degree <origin <branch <size <price <degree <origin <Physics <Biology
$closing_brackets:
2718 1687 625 360 179 207 241 273 612 447 475 509 541 1142 900 713 741 775 808 844 882 1129 948 976 1012 1044 1077 1

Estabelecer relações de nodais

Agora é hora para a segunda fase na análise de operações de motor. Nesta fase mais complexa, as seqüências de $leading_brackets e $closing_brackets estabelecem as relações pai-filho e irmão, entre todos os nós do XML que está sendo analisado. Em primeiro lugar, um número de variáveis é estabelecido:

# These variables will be used to build an automatic list of XPath queries
$xpaths = @()
$xpaths_sorted = @()
$xpath = @()
[string]$xpath2 = $null

Em seguida, um primeiro emparelhamento de esquerda adjacente e colchetes de fechamento é fixo:

$first_open = $leading_brackets[0]
$first_closed = $closing_brackets[0]
$second_open = $leading_brackets[1]
$second_closed = $closing_brackets[1]

E alguns contadores de loop são criados:

$loop_ctr = 1
$loop_ctr3 = 0

O motor irá analisar, iterativamente, não mais vezes do que o valor da variável $ctr incrementado durante a primeira fase em construção o $leading_brackets e outros arrays (o seguinte se a declaração é o teste decisivo em termos do que estabelece a estrutura nodal do XML):

if($second_closed -lt $first_closed)

Se o valor de second_closed $ é inferior (-lt) o valor de first_closed $, uma relação de filho é estabelecido:

<ElementOneName>text for this element
  <ChildElementName>this one closes up before its parent does</ChildElementName>
</ElementOneName>

Com um nó filho detectado, as variáveis são redefinidas para os próximos dois pares adjacentes de colchetes de abertura-fechamento, os contadores que são incrementados e a matriz de xpath $ vital é preenchida com um novo elemento:

$first_open = $leading_brackets[$loop_ctr]
$first_closed = $closing_brackets[$loop_ctr]
$second_open = $leading_brackets[$loop_ctr + 1]
$second_closed = $closing_brackets[$loop_ctr + 1]
$loop_ctr2 +=1
#if($loop_ctr2 -gt $depth){$loop_ctr2 -= 1}
$depth_trial+=1
$xpath += '/' + $leading_value[$loop_ctr-1]
$loop_ctr+=1

Agora, você atingiu o estágio de processamento crítico para o mecanismo de análise: O que fazer quando a relação pai-filho já não tem.

Uma questão preliminar é eliminar as duplicatas que surgirão no decorrer da análise de operações de motor. Para isso, a variável que contém a matriz inteira de consultas XPath (que é o valor da chave construído pelo mecanismo de análise) é opinião elemento por elemento para garantir que ele já não contém o candidato proposto novo para inclusão em $xpaths, que neste momento é o valor atual de $xpath, estabelecida-se na oitava linha do código em Figura 7.

Figura 7 verificação para duplicar Xpaths

$is_dupe = $false
  foreach($xp in $xpaths)
  {
  $depth = $xpath.Length
  $xp = $xp.Replace('/////','')
  $xpath2 = $xpath
  $xpath2 = $xpath2.Replace(" ","")
  $xpath2 = $xpath2.Replace("<","")
  if($xp -eq $xpath2)
  {
  $is_dupe = $true
  #write-host 'DUPE!!!'
  break
}

Se o valor atual de xpath $ não é um duplicado, ele é acrescentado à matriz $xpaths e $xpath é recriada como uma matriz vazia para sua próxima utilização:

if($is_dupe -eq $false){$xpaths += ($xpath2 + '/////');}
$xpath = @()
$xpath2 = $null

O dispositivo essencial usado pelo mecanismo de análise para continuar com o XML iterativamente é reconstruir as matrizes em cada itera-ção. Para fazer isso, a primeira etapa é para criar novos objetos de matriz provisória como dispositivos de transição:

$replacement_array_values = @()
$replacement_array_opens = @()
$replacement_array_closes = @()
$finished = $false
$item_ct = 0

O motor percorre a matriz de leading_value $ e filtra apenas o que atual:

foreach($item in $leading_value)
{
if($item -eq $leading_value[$loop_ctr - 1] -and $finished -eq $false)
{
$finished = $true
$item_ct+=1
continue  #because this one should be filtered out
}

Valores não filtrados são preenchidos para a matriz provisória. Todas as três matrizes são preenchidas através de associação, porque a matriz de valores de nome do elemento corresponde em sua indexação com as matrizes de colchete de abertura e fechamento:

$replacement_array_values += $item
$replacement_array_opens += $leading_brackets[$item_ct]
$replacement_array_closes += $closing_brackets[$item_ct]
$item_ct +=1

Quando terminarem as três matrizes provisórias, as três matrizes permanentes recebem seus novos valores:

$leading_value = $replacement_array_values
  $opening_brackets = $replacement_array_opens
  $closing_brackets = $replacement_array_closes
  $loop_ctr+=1

A próxima iteração da primeira fase do mecanismo de análise é preparada por inicializar os primeiros pares adjacentes de colchetes:

$first_open = $leading_brackets[0]
$first_closed = $closing_brackets[0] 
$second_open = $leading_brackets[1] 
$second_closed = $closing_brackets[1] 
$loop_ctr = 1
$loop_ctr2 = 1
continue  # Sends the engine back to the top of the loop

Finalmente, para completar o conjunto de consultas XPath, você gerar caminhos curtos que não poderia ter incluído o processo descrito anteriormente. Por exemplo, no exemplo atual, sem esta etapa extra de último, a \Sciences\Chemistry de XPath não seria incluído. A lógica subjacente é que cada versão mais curta de todas as consultas XPath também existe, sem duplicatas de teste. A função que executa este passo é AddMissingShortPaths, que você pode ver no download do código deste artigo (archive.msdn.microsoft.com/mag201208PowerShell).

Com todas as consultas XPath automáticas na mão, você está pronto para criar um aplicativo Windows Forms para usuários. Entretanto, as consultas XPath apenas produzidas são colocadas no arquivo C:\PowerShell\XPATHS.txt através do Windows PowerShell >> sintaxe de saída.

Construindo o aplicativo de formulários do Windows

Porque Windows PowerShell hospeda classes e bibliotecas .net, você pode escrever o código a seguir e assim disponibilizar seu aplicativo Windows Forms e as classes de desenho do .net:

[void] [Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")

Com esses blocos de construção básicos no lugar, você pode criar um formulário e seus controles, como segue:

$form= New-Object Windows.Forms.Form
$form.Height = 1000
$form.Width = 1500
$drawinfo = 'System.Drawing'
$button_get_data = New-Object Windows.Forms.button
$button_get_data.Enabled = $false
$text_box = New-Object Windows.Forms.Textbox
$button_get_data.Text = "get data"
$button_get_data.add_Click({ShowDataFromXMLXPathFilter})

É interessante notar que add_Click é a sintaxe do Windows PowerShell para anexar a um evento de um controle — neste caso, anexar uma chamada de função para o evento de click do botão. O código em Figura 8 adiciona botões e caixas de texto.

Figura 8 Adicionando botões e caixas de texto

$pointA = New-Object System.Drawing.Point 
$listbox = New-Object Windows.Forms.Listbox 
$form.Controls.Add($listbox)
$listbox.add_SelectedIndexChanged({PopulateTextBox})
$form.Controls.Add($button_get_data)
$form.Controls.Add($text_box)
$pointA.X = 800 
$pointA.Y = 100 
$button_get_data.Location = $pointA
$button_get_data.Width = 100
$button_get_data.Height = 50
$pointA.X = 400 
$pointA.Y = 50 
$text_box.Location = $pointA
$text_box.Width = 800

Para preencher o listbox $ com sua coleção de consultas XPath, faça o seguinte:

foreach($item in $xpaths)
{
$listbox.Items.Add($item.Substring(0,$item.Length - 5))
# Each row in the listbox should be separated by a blank row
$listbox.Items.Add('     ')
}

A interface do usuário

Figura 9 exibe a interface do usuário com as consultas XPath geradas pela ferramenta mostrada à esquerda, um dos quais foi selecionado pelo usuário.

Selecting an XPath Query
Figura 9 selecionando uma consulta XPath

Na etapa final, o usuário pressiona o botão de GetXMLData e produz os resultados mostrados na Figura 10.

The Results Window
Figura 10 A janela de resultados

Aí está ele — uma interface de usuário simple para leitura e edição de arquivos XML, criados inteiramente com o Windows PowerShell. Em próximos artigos on-line do MSDN Magazine, vou continuar neste assunto, mostrando-lhe como lidar com arquivos XML que usam espaços para nome, bem como demonstram o uso das técnicas mostradas aqui para permitir a edição de arquivos XML através da interface.

Joe Leibowitz é um consultor especializado em projetos de infra-estrutura. Ele pode ser contatado em joe.leibowitz@bridgewaresolutions.com.

Agradecemos ao seguinte especialista técnico pela revisão deste artigo: Thomas Petchel