Visual Basic 6 - Integrando XML com VB6


No artigo - XML - eXtensible Markup Language - Introdução - abordei os conceitos básicos sobre XML ; no artigo Usando XSL - Extensible Style Language - mostrei como trabalhar com XLS para exibir arquivos XML em um navegador. Muito bem ! E se você precisar acessar um arquivo XML a partir do Visual Basic ? Este é o assunto deste artigo.

Para acessar um arquivo XML usando o Visual Basic você pode escolher : criar você mesmo um programa para fazer a leitura ou usar um programa já pronto para fazer o serviço . Como você não vai querer reinventar a roda não é mesmo, creio que a segunda opção esta de bom tamanho.

Um interpretador para ler arquivos XML é conhecido como um XML Parser , e, existem muitos programas que cumprem esta função . Neste artigo eu vou falar sobre o XML DOM ( Document Object Model).

O XML DOM utiliza o modelo Tree-Based (baseado em árvore) e cria uma estrutura de dados na memória para representar os dados do arquivo XML permitindo acessar de forma aleatória qualquer nó dentro do documento XML.

O XML DOM também representa um modelo de objeto a partir do qual podemos interpretar e criar dados ; como este modelo é um modelo baseado em árvore o modelo DOM vai permitir a nossa aplicação Visual Basic navegar através da árvore com nós representando elementos , atributos , comentários e outras estruturas. Abaixo do nível do nó raiz ( o topo ) temos os nós filhos , parentes e irmãos interligados ou não.

A API XML DOM permite o modelo de objeto representar um nó e obter informações sobre um nó e os demais nós a ele ligados . A interface Node (nó) é o coração do esquema DOM ; é praticamente tudo que precisamos para obter as informações em um arquivo XML. Abaixo temos uma representação desta interface e os principais tipos de nós.

Tipo de Nó Valor Descrição
NODE_ELEMENT 1 Representa um elemento
NODE_ATTRIBUTE 2 Representa um atributo de um elemento
NODE_TEXT 3 Representa uma tag com texto
NODE_PROCESSING_INSTRUCTION 7 Representa uma instrução e processamento de um docmento XML
NODE_COMMENT 8 Representa um comentário
NODE_DOCUMENT 9 Reresenta um objeto documento
NODE_DOCUMENT_TYPE 10 Representa a declaração do tipo de documento indicado pela tag - <IDOCTYPE>
  Então resumindo :
  • Cada objeto implementado via API DOM é um Nó ( Node )
  • O objeto DOMDocument contém o documento XML.
  • A partir do DOMDocument acessamos os dados XML através da propriedade - documentElement - que esta disponível a partir da interface IXMLDOMElement ou IXMLDOMNode
  • Essas interfaces possuem a propriedade - childNodes - a partir da qual interamos através de cada elemento - child , comentário , etc.. do Nó Pai.
  • A interface - IXMLDOMNodeList - permite o acesso a coleção de Nós ( Nodes) como filhas de um elemento.

A hierarquia das interfaces presente no modelo DOM esta representado abaixo. (somente as interfaces mais comuns).

O parser XML usado no Visual Basic é o MXSML - (http://msdn.microsoft.com/xml) e é ele que vamos usar neste artigo.

Lendo e exibindo os dados de um arquivo XML

Nosso objetivo será ler e exibir os dados de um arquivo xml em um programa Visual Basic . Como exemplos eu peguei um arquivo xml qualquer chamado agenda.xml. Este arquivo possui a seguinte estrutura :

<?xml version="1.0"?>
<!-- *********** agenda para pessoas *********** -->
<!DOCTYPE PEOPLE SYSTEM "agenda.dtd">
<PEOPLE>
	<PERSON PERSONID="p1">
		<NAME>Mark Wilson</NAME>
		<ADDRESS>911 Somewhere Circle, Canberra, Australia</ADDRESS>
		<TEL>(++612) 12345</TEL>
		<FAX>(++612) 12345</FAX>
		<EMAIL>markwilson@somewhere.com</EMAIL>
	</PERSON>
	<PERSON PERSONID="p2">
		<NAME>Tracey Wilson</NAME>
		<ADDRESS>121 Zootle Road, Cape Town, South Africa</ADDRESS>
		<TEL>(++2721) 531 9090</TEL>
		<FAX>(++2721) 531 9090</FAX>
		<EMAIL>Tracey Wilson@somewhere.com</EMAIL>
	</PERSON>
	<PERSON PERSONID="p3">
		<NAME>Jodie Foster</NAME>
		<ADDRESS>30 Animal Road, New York, USA</ADDRESS>
		<TEL>(++1) 3000 12345</TEL>
		<FAX>(++1) 3000 12345</FAX>
		<EMAIL>Jodie Foster@somewhere.com</EMAIL>
	</PERSON>
	<PERSON PERSONID="p4">
		<NAME>Lorrin Maughan</NAME>
		<ADDRESS>1143 Winners Lane, London, UK</ADDRESS>
		<TEL>(++94) 17 12345</TEL>
		<FAX>++94) 17 12345</FAX>
		<EMAIL>Lorrin Maughan@somewhere.com</EMAIL>
	</PERSON>
	<PERSON PERSONID="p5">
		<NAME>Steve Rachel</NAME>
		<ADDRESS>90210 Beverly Hills, California, USA</ADDRESS>
		<TEL>(++1) 2000 12345</TEL>
		<FAX>(++1) 2000 12345</FAX>
		<EMAIL>Steve Rachel@somewhere.com</EMAIL>
	</PERSON>
	<PERSON PERSONID="p6"><NAME>Macoratti</NAME>
                 <ADDRESS>Rua doze , 100</ADDRESS>
                 <FAX>017-2247766</FAX>
                 <TEL>1632-4654</TEL>
                 <EMAIL>macoratti@riopreto.com.br</EMAIL>
         </PERSON>
</PEOPLE>

Note que o arquivo agenda.xml faz referência ao arquivo agenda.dtd cuja estrutra é a seguinte:

<!ENTITY USA "United States of America">
<!ENTITY UK "United Kingdom">
<!ELEMENT PEOPLE ( PERSON+ ) >
<!ELEMENT PERSON ( NAME, ADDRESS, TEL, FAX, EMAIL ) >
<!ATTLIST PERSON PERSONID ID #REQUIRED>
<!ELEMENT NAME (#PCDATA)>
<!ELEMENT ADDRESS ( #PCDATA ) >
<!ELEMENT TEL ( #PCDATA ) >
<!ELEMENT FAX ( #PCDATA ) >
<!ELEMENT EMAIL ( #PCDATA ) >

Então vamos ter que ler os dados do arquivo agenda.xml e exibir em um formulário Visual Basic. Já vou adiantando o layout do formulário . O jeitão dele é dado abaixo:

A idéia é a seguinte:

- Vou ler e exibir os dados do arquivo agenda.xml em um controle Treeview

- Quando o usuário clicar em um os dados serão exibidos nas caixas de texto do formulário

- Vou dar a opção do usuário ver o arquivo XML usando um controle WebBrowser para exibir os dados do arquivo agenda.xml

- Darei também a opção de poder incluir/excluir um elemento no arquivo agenda.xml e tratá-lo como sendo um novo dado

Quando o usuário clicar no botão :Preenche os dados do arquivo agenda.xml serão exibidos como na figura ao lado.

- Ao clicar em um Nó (sinal de +) os dados serão exibidos nas caixas de texto

Agora vamos ao código do projeto:

1- Inicie um novo projeto no Visual Basic e faça as seguintes referências no mesmo:

2- Código da seção General Declarations : Declara as variáveis visíveis no formulário.

Option Explicit
Private m_objDOMPessoa As DOMDocument
Private m_blnItemClicked As Boolean
Private m_strXmlPath As String
Dim flagpreenche As Boolean

3- Código do evento Load do formulário: definimos o caminho do arquivo agenda.xml e atribuimos o valor False a variável - flagpreenche.

 Private Sub Form_Load()
   m_strXmlPath = App.Path & "\agenda.xml"
   flagpreenche = False
End Sub

4- Agora temos o código do botão - Preenche - que irá carregar e ler os dados do arquivo agenda.xml e exibí-lo no controle - tvwPessoa.

Private Sub cmdPreencher_Click()
Dim objPessoaRoot As IXMLDOMElement 
Dim objPessoaElement As IXMLDOMElement 
Dim tvwRoot As Node
Dim X As IXMLDOMNodeList

flagpreenche = True
cmdxml.Enabled = True

  Set m_objDOMPessoa = New DOMDocument
  m_objDOMPessoa.resolveExternals = True
  m_objDOMPessoa.validateOnParse = True

'carrega o XML no documento DOM
m_objDOMPessoa.async = False
Call m_objDOMPessoa.Load(m_strXmlPath)

'verifica se a carga do XML foi feita com sucesso
If m_objDOMPessoa.parseError.reason <> "" Then
   MsgBox m_objDOMPessoa.parseError.reason
   Exit Sub
End If

'obtem o elemento raiz do XML
Set objPessoaRoot = m_objDOMPessoa.documentElement
'define as propriedades do Treeview
tvwPessoa.LineStyle = tvwRootLines
tvwPessoa.Style = tvwTreelinesPlusMinusText
tvwPessoa.Indentation = 400

'verifica se o treeview ja foi preenchido
'se ja foi remove o raiz que remove tudo
If tvwPessoa.Nodes.Count > 0 Then
  tvwPessoa.Nodes.Remove 1
End If

' inclui um nó filho ao nó rai do TreeView
Set tvwRoot = tvwPessoa.Nodes.Add()
tvwRoot.Text = objPessoaRoot.baseName

' iteracao atraves de cada elemento para encher a arvore que por sua vez 
interagem atraves de cada childNode do element(objPessoaElement)
For Each objPessoaElement In objPessoaRoot.childNodes
          PreencherTreeWithChildren objPessoaElement
Next
' carregamos o controle webbrowser com o conteúdo do arquivo xml
webTarget.Navigate m_strXmlPath
cmdExcluir.Enabled = True
cmdIncluir.Enabled = True

End Sub

O código acima invoca o procedimento - PreencherTreeWithChildren - para preencher TreeView com os elementos. O código é o seguinte:

Private Sub PreencherTreeWithChildren(objDOMNode As IXMLDOMElement)

Dim objNameNode As IXMLDOMNode
Dim objAttributes As IXMLDOMNamedNodeMap
Dim objAttributeNode As IXMLDOMNode
Dim objPessoaElement As IXMLDOMElement
Dim intIndex As Integer

Dim tvwElement As Node
Dim tvwChildElement As Node

'obtem o nome do elemento selecionado
Set objNameNode = objDOMNode.selectSingleNode("NAME")

'inclui os elementos aos nós
Set tvwElement = tvwPessoa.Nodes.Add(1, tvwChild)
tvwElement.Text = objNameNode.parentNode.nodeName & ": " _
& objNameNode.nodeTypedValue

Set objAttributes = objDOMNode.Attributes

'verifica os atributos
If objAttributes.length > 0 Then

' obtendo o item para a referencia ''PERSONID',
' com NameNodeListMap para o Nó atual
Set objAttributeNode = objAttributes.getNamedItem("PERSONID")

'armazena o valor na tag do treeview
tvwElement.Tag = objAttributeNode.nodeValue
End If

tvwElement.EnsureVisible
intIndex = tvwElement.Index

'interagem através dos Nós filhos(childNodes) do objeto DOMNode
' para preencher o TreeView os seus valores
For Each objPessoaElement In objDOMNode.childNodes
  Set tvwChildElement = tvwPessoa.Nodes.Add(intIndex, tvwChild)
  tvwChildElement.Text = objPessoaElement.nodeTypedValue
Next

End Sub

Quando o usuário clica em um Nó ele se expande e exibe os detalhes no controle TreeView e nas caixas de texto. O código do evento Click do controle treeView - tvwPessoa é o seguinte:

Private Sub tvwPessoa_Click()
Dim objSelNode As Node

If m_blnItemClicked = True Then
  m_blnItemClicked = False
  Exit Sub
End If

Set objSelNode = tvwPessoa.SelectedItem
  populatePessoaDetalhes objSelNode
End Sub

Para exibir o conteúdo do arquivo XML , basta clicar no botão - XML >> . O controle WebBrowser exibe os dados do arquivo xml conforme abaixo:( O código esta ao lado)

Private Sub Cmdxml_Click()
If cmdxml.Caption = "XML >>" Then
  Me.Height = 7200
  webTarget.Visible = True
  cmdxml.Caption = "<< XML"
ElseIf cmdxml.Caption="<<XML" Then
  Me.Height = 4215
  webTarget.Visible = False
  cmdxml.Caption = "XML >>"
End If
End Sub
- Codigo para exibir os dados
do arquivo agenda.xml no controle
webbrowser.

- Os código para expandir e retrair o Nó selecionado é o seguinte:

Private Sub tvwPessoa_Collapse(ByVal Node As MSComctlLib.Node)
  populatePessoaDetalhes Node
  m_blnItemClicked = True
End Sub

Private Sub tvwPessoa_Expand(ByVal Node As MSComctlLib.Node)
  populatePessoaDetalhes Node
  m_blnItemClicked = True
End Sub

- Ao clicar no botão - Incluir - podemos incluir um novo elemento no arquivo agenda.xml . O código associado ao evento click do botão é dado abaixo:

Private Sub cmdIncluir_Click()
  lblElemento.Caption = ""
  txtNome.Text = ""
  txtEndereco.Text = ""
  txtTel.Text = ""
  txtFax.Text = ""
  txtEmail.Text = ""
  cmdIncluir.Enabled = True
End Sub

- Para salvar um novo elemento usamos o código associado ao evento Click do botão - Salvar

Private Sub cmdSalvar_Click()
  salvarNovaPessoa
  cmdAdd.Enabled = False
End Sub

- Este código chama a procedure - salvarNovaPessoa cujo código é :

Private Sub salvarNovaPessoa()

'cria um novo elemento e inclui no objeto dom
Dim objPerson As IXMLDOMElement
Dim objNewChild As IXMLDOMElement

'cria um novo elemento PERSON
Set objPerson = m_objDOMPessoa.createElement("PERSON")
objPerson.setAttribute "PERSONID", getNewID
m_objDOMPessoa.documentElement.appendChild objPerson

'cria um elmeneto (objPerson), e inclui no No Filho(childNodes)
Set objNewChild = m_objDOMPessoa.createElement("NAME")
objNewChild.Text = txtName.Text
objPerson.appendChild objNewChild

Set objNewChild = m_objDOMPessoa.createElement("ADDRESS")
objNewChild.Text = txtAddress.Text
objPerson.appendChild objNewChild

Set objNewChild = m_objDOMPessoa.createElement("TEL")
objNewChild.Text = txtTel.Text
objPerson.appendChild objNewChild

Set objNewChild = m_objDOMPessoa.createElement("FAX")
objNewChild.Text = txtFax.Text
objPerson.appendChild objNewChild

Set objNewChild = m_objDOMPessoa.createElement("EMAIL")
objNewChild.Text = txtEmail.Text
objPerson.appendChild objNewChild

'sincroniza com o TreeView
PreencherTreeWithChildren objPerson

m_objDOMPessoa.save m_strXmlPath

webTarget.Refresh
Set objPerson = Nothing
Set objNewChild = Nothing

End Sub

- Para excluir um elemento usamos o seguinte código associado ao evento Click do botão - Excluir:

Private Sub cmdExcluir_Click()
  deleteSelectedPerson tvwPessoa.SelectedItem
End Sub

- O código acima chama a função - deleteSelectedPerson - que tem o seu código exibido abaixo:

Private Sub populatePessoaDetalhes(objSelNode As Node)

' preenche os textbox dos formulario com os detalhes do documento
Dim objPessoaElement As IXMLDOMElement
Dim objChildElement As IXMLDOMElement

If objSelNode Is Nothing Then Exit Sub

'ignora a selecao do TreeView se nao foi clicado um No "PERSON"
If Trim(objSelNode.Tag) <> "" Then

'obtem o no(element type), que possui um atributo ao valor
'da tag do TreeView
Set objPessoaElement = m_objDOMPessoa.nodeFromID(objSelNode.Tag)

lblElemento.Caption = objPessoaElement.nodeName & ": ID = " & _
objPessoaElement.Attributes(0).nodeValue

'interagem atraves dos nos achadose preenche o texto com os conteudo dos nos
For Each objChildElement In objPessoaElement.childNodes

'verifica o tipo de No que estamos tratando
If objChildElement.nodeType = NODE_ELEMENT Then
   Select Case UCase(objChildElement.nodeName)
  Case "NAME"
    txtNome.Text = objChildElement.nodeTypedValue
  Case "ADDRESS"
    txtEndereco.Text = objChildElement.nodeTypedValue
  Case "TEL"
    txtTel.Text = objChildElement.nodeTypedValue
  Case "FAX"
    txtFax.Text = objChildElement.nodeTypedValue
  Case "EMAIL"
    txtEmail.Text = objChildElement.nodeTypedValue
  End Select
 End If
Next objChildElement
End If

Set objChildElement = Nothing
Set objPessoaElement = Nothing
End Sub

Quando os dados são exibidos o codigo ID do elemento é exibido através seguinte código :

Private Function getNewID() As String
   getNewID = "p" & m_objDOMPessoa.documentElement.childNodes.length + 1
End Function

Com isto acabei de mostrar como tratar arquivos XML no VB usando o DOM ...

Pegue o código do projeto aqui : vbxml.zip - ( 6 KB )

Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti