Como leer la
información de un archivo XML con XML Parser
Por Toni Planas
http://www.fpress.com/
msxml.zip
Visual Foxpro desde su versión 7 incluye una serie de
funciones relacionadas con XML, pero el objetivo es este documento es
proporcionar al lector otro método para leer información en formato XML sin las
limitaciones de las funciones que proporciona Visual Foxpro.
Cuando intente utilizar XMLTOCURSOR() para recuperar
información en formato XML me di cuenta que solo podía leer el primer nivel
dentro de la jerarquía, el resto de niveles XMLTOCURSOR() intenta colocarlos en
un campo memo sin conseguirlo del todo, también comprobé que no podía recuperar los atributos de las
etiquetas XML .
MSXML Parser es una DLL que Microsoft empezó a
distribuir con Internet Explorer 5, la última versión de esta DLL es la 4.0, se
puede descargar de la web de Microsoft.
Veamos como leer todos los niveles de un archivo XML
con sus atributos. Para ello utilizaremos un archivo XML que contiene
información sobre CDs de música (Género, Tipo de intérprete, Intérprete,
Título, Número de temas del CD y lista de temas con su duración en minutos) algunos de estos datos son atributos de
algún nodo (Género, Tipo de intérprete, Número de temas y duración del tema) el
resto es información contenida en el propio nodo.
Los archivos utilizados en el ejemplo son cds.xsd, archivo de esquema, cds.xml, archivo de datos.
CDs.XSD
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="CDs">
<xs:annotation>
<xs:documentation>Compact Disc</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="CD" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="Artista">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Tipo" type="xs:string" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="Titulo">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string"/>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="Temas">
<xs:complexType>
<xs:sequence>
<xs:element name="Tema" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Duracion" type="xs:string" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="NumeroDeTemas" type="xs:integer" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="Genero" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
CDs.XML
<?xml version="1.0"
encoding="UTF-8"?>
<CDs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="CDs.xsd">
<CD Genero="Pop">
<Artista Tipo="Cantautor">Joaquín Sabina</Artista>
<Titulo>Dímelo en la calle</Titulo>
<Temas NumeroDeTemas="14">
<Tema Duracion="4:12">No permita la virgen</Tema>
<Tema Duracion="3:36">Vámos pa'l sur</Tema>
<Tema Duracion="4:54">La canció más hermosa
del mundo</Tema>
<Tema Duracion="2:57">Como un dolor de muelas</Tema>
<Tema Duracion="4:03">69 punto G</Tema>
<Tema Duracion="5:05">Peces de ciudad</Tema>
<Tema Duracion="4:57">El café de nicanor</Tema>
<Tema Duracion="3:45">Lágrimas de plástico
azul</Tema>
<Tema Duracion="4:31">Yo también sé jugarme
la boca</Tema>
<Tema Duracion="4:47">Arenas movedizas</Tema>
<Tema Duracion="4:37">Ya eyaculé</Tema>
<Tema Duracion="3:43">Cuando me hablan del
destino</Tema>
<Tema Duracion="5:05">Camas vaciás</Tema>
<Tema Duracion="4:28">Semos diferentes</Tema>
</Temas>
</CD>
<CD Genero="Pop">
<Artista Tipo="Banda">Dire Straits</Artista>
<Titulo>Dire Straits</Titulo>
<Temas NumeroDeTemas="9">
<Tema Duracion="3:59">Down to the waterline</Tema>
<Tema Duracion="5:22">Water of love</Tema>
<Tema Duracion="3:19">Setting me up</Tema>
<Tema Duracion="4:09">Six blade knife</Tema>
<Tema Duracion="2:57">Southbound again</Tema>
<Tema Duracion="5:34">Sultans of swing</Tema>
<Tema Duracion="6:14">In the gallery</Tema>
<Tema Duracion="4:42">Wild west end</Tema>
<Tema Duracion="4:54">Lions</Tema>
</Temas>
</CD>
<CD Genero="Pop">
<Artista Tipo="Banda">Sopa de cabra</Artista>
<Titulo>Plou i fa sol</Titulo>
<Temas NumeroDeTemas="12">
<Tema Duracion="3:15">Camins</Tema>
<Tema Duracion="3:39">Si et va bé</Tema>
<Tema Duracion="3:41">Plou i fa sol</Tema>
<Tema Duracion="3:58">Els teus somnis</Tema>
<Tema Duracion="3:56">Larg viatge</Tema>
<Tema Duracion="3:13">Deixa'm dir una cosa</Tema>
<Tema Duracion="3:48">Sempre hi haurà un bon
motiu</Tema>
<Tema Duracion="3:20">Només ès amor</Tema>
<Tema Duracion="2:39">La darrera mirada
enrere</Tema>
<Tema Duracion="5:20">Cada minut</Tema>
<Tema Duracion="4:36">Tot el que vull</Tema>
<Tema Duracion="4:16">Quan es facil fosc</Tema>
</Temas>
</CD>
</CDs>
Para poder leer todos los niveles nos apoyaremos en una sencilla
función de tipo recursivo a la que le pasaremos el nodo actual, siendo la raíz
del documento XML el primer parámetro a pasar.
Aquí tenéis el código de lo
expuesto:
LOCAL xdoc AS MSXML2.DOMDocument
CLEAR
*!* Creamos un
objeto basado en MSXML
xdoc=CREATEOBJECT('MSXML2.DOMdocument')
*!* Cargamos
el archivo XML a procesar
xdoc.LOAD('CDs.xml')
*!* Llamamos a
la función LeerCDs pasándole el nodo raíz (DCs)
LeerCDs(xdoc.documentElement.childNodes)
FUNCTION LeerCDs
LPARAMETERS root AS MSXML2.IXMLDOMNode
LOCAL
CHILD AS MSXML2.IXMLDOMNode
*!* Aqui se procesan los nodos (DC,Artista,Titulo,Temas y Tema)
FOR EACH CHILD IN root
IF
CHILD.nodeName="CD"
*!* Mostramos la información referente al CD
? REPLICATE("=",30)
*!* CHILD.ATTRIBUTES.ITEM(0).TEXT hace
referencia al primer atributo del nodo
? "Género :
"+CHILD.ATTRIBUTES.ITEM(0).TEXT
ELSE
IF CHILD.nodeName="Artista"
*!* Mostramos la información referente
al artista
? "Tipo de Artista :
"+CHILD.ATTRIBUTES.ITEM(0).TEXT
?
"Artista : "+CHILD.TEXT
ELSE
IF CHILD.nodeName="Titulo"
*!* Mostramos la información
referente al título
? "Título del DC :
"+CHILD.TEXT
? REPLICATE("=",30)
ELSE
IF
CHILD.nodeName="Temas"
*!* Mostramos el número de temas
? "Número de temas del CD :
"+CHILD.ATTRIBUTES.ITEM(0).TEXT
ELSE
IF
CHILD.nodeName="Tema"
*!* Mostramos los temas con su duración
? CHILD.TEXT+"
"+CHILD.ATTRIBUTES.ITEM(0).TEXT
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
*!*
Si el nodo que estamos procesando tiene
descendencia volvemos a llamar a la función LeerCDs pasandole el nodo actual
*!* Esto sucede cuando se procesa el nodo
(Temas)
IF CHILD.hasChildNodes
LeerCDs(CHILD.childNodes)
ENDIF
ENDFOR
ENDFUNC
FoxPress – Abril de 2003
© 2003 FoxPress. All rights reserved