MetaCard y Revolution: Herramientas de autor multiplataforma para multimedia | ||
---|---|---|
Anterior | Capítulo 7. Texto | Siguiente |
Examinaremos en este apartado las recientes incorporaciones de funciones que permiten el acceso a los contenidos de un documento XML y sus posibilidades de procesado. Estas aparecieron de forma independiente en base al trabajo de SonOfThunder (XMLLibrary) y que pudimos ver empleadas de forma gráfica en el control mejorado de Altuit (XML TreeView List Control).
Para trabajar con un fichero XML se puede hacer directamente accediendo a sus contenidos: puesto que es un fichero de texto, no representa mayores problemas. A partir de aquí se pueden utilizar las funciones de búsqueda de texto tradicionalmente incluídas en MetaCard o Revolution. Pero, desde la perspectiva de XML, un documento es una estructuración jerárquica de sus contenidos. Este concepto permite definir un modelo del documento que suele expresarse en términos de un árbol, de esta forma el procesado de un documento se convierte en las posibles secuencias de recorrido sobre el mismo en las que se irán (posiblemente) realizando operaciones de consulta, edición y borrado.
Así que a partir de ahora, nos referiremos al contenido de un documento como una serie de nodos organizados de forma jerárquica [1] . Estos nodos podrán estar vacios o no. Dentro de los segundos se podrán encontrar diferentes combinaciones de: contenido del nodo, atributos de la etiqueta que lo define y, posiblemente, más nodos. En este sentido, la presente librería nos ofrece funciones e instrucciones para procesar estos objetos y que podemos agrupar en:
Operaciones con ficheros que contienen o contendrán documentos XML, como por ejemplo revXMLText
y revCreateXMLTreeFromFile
(?).
Creación de árboles y liberación de los recursos asignados a estos, como son revXMLTree
, revXMLTrees
y revCreateXMLTree
.
Recorrido de árbol en forma absoluta desde la raiz, relativa desde un nodo o en función de la relación padre-hijo existentes. En este grupo encontraremos revXMLNumberOfChildren
, revXMLParent
revXMLNextSibling
, revXMLPreviousSibling
.
Consulta y modificación de nodos, por ejemplo, revXMLRootNode
, revXMLNodeContents
, revAddXMLNode
, revXMLDeleteNode
, revXMLPutIntoNode
, revXMLChildContents
, revXMLChildName
, revXMLFirstChild
y revXMLMAtchingNode
.
Consulta y modificación de atributos de un elemento, entre las que se encuentran revXMLAttribute
, revXMLAttributeValues
y revXMLAttributeValue
.
Manejo de DTDs y validación de documentos XML, como revXMLAddDTD
y ...
.
Figura 7-10. Pila para la visualización de las funciones sobre tratamiento de documentos XML en Revolution.
Figura 7-11. Ejemplo de fichero XML: animals.xml.
<?xml version="1.0"?> <endangered_species> <animal> <name language="english">Tiger</name> <name language="latin">Panthera tigris</name> <threat>poachers</threat> <weight>500</weight> </animal> <animal> <name language="english">Kitty</name> <threat>My Dog!</threat> </animal> <animal> <name language="english">dog</name> <threat>cat</threat> </animal> </endangered_species>
Para exponerlas se van a ir desglosando las piezas que forman un pequeño tutorial visual (del cual se puede ver su apariencia en la Figura 7-10) acerca de qué ocurre tras ejecutar cada una de las funciones indicadas. En las siguientes figuras se mostrarán los resultados obtenidos al procesar un mismo fichero XML. El contenido [2] del fichero animals.xml que acompaña a la distribución de Revolution y que se muestra en la Figura 7-11, junto al DTD utilizado.
Figura 7-12. Ejemplo de fichero DTD: animals.dtd. Una pequeña nota: significa "en peligro" (de extinción, en este caso), threat significa amenaza y poachers son "cazadores furtivos".
<! ELEMENT endangered_species (animal+)> <!ELEMENT animal (name+, threat, weight)> <!ELEMENT name (#PCDATA)> <!ATTLIST name language (english | latin ) #REQUIERED> <!ELEMENT threat (#PCDATA)> <!ELEMENT weight (#PCDATA)>
Pero, para que sea eficiente, es conveniente utilizar las funciones incorporadas a partir de la versión 2.5 de MetaCard o la 2.0 de Revolution. En los siguientes puntos se irán desgranando estas funciones de un manera sucinta, ofreciendo de esta manera una sencilla aproximación a la labor y posibilidades de cada una de estas funciones.
Nota: La salida de todas las secuencias de código se mostrará en un campo de texo adyacente al botón que las inicia para poder comprobar el resultado devuelto.
Todas las funciones pueden devolver un código de error (una cadena de texto que empieza con 'xmlerr'), así que es interesante comprobar el resultado que devuelven tras su ejecución. Aquí, no está hecho para centrar la atención del lector en las funciones y sus parámetros, minimizando el número de instrucciones empleadas. Pero, de forma general se puede utilizar la secuencia siguiente:
put nombreFuncion( parametro1, .., parametroN) if char 1 to 6 of it is "xmlerr" \ then\ answer error "Se ha producido un error al ejecutar" & return &\ "nombreFuncion( parametro1, .., parametroN) " & return &\ title "[" & the short name of me & "]"
Para cargar un fichero XML se puede leer directamente del disco como un fichero más, pero para empezar a trabajar con él de una forma que permita su proceso hay que crear una estructura en forma de árbol que haga eficiente su recorrido.
La función revCreateXMLTree
(XMLText
,parseBadData
,createTree
,sendMessages
) devuelve un valor númerico que es utilizado para referirse al árbol que ha creado, con las particularidades que indican sus parámetros.
En nuestro ejemplo, se ha concretado en la siguiente forma:
# revCreateXMLTree on mouseUp put revCreateXMLTree(field "fitxerXML","false", true, false) into fld "docID" end mouseUp
Que obtiene el contenido XML no directamente de un fichero, si no que lo toma del campo de texto indicado (
field "fitxerXML").
Y en el campo de texto indicado para devolver el resultado (
field "docID"), aparece un valor numérico indicando que la operacion ha terminado de manera satisfactoria. En caso de error se vería la cadena correspondiente empezando con, como ya se ha dicho, la palabra xmlerr. En nuestro caso, este valor es el que utilizaremos en las posteriores funciones para referirnos a la representación interna que se acaba de crear con esta función.
Si ya se ha accedido al contenido del fichero y se ha creado la estructura de árbol, podemos empezar a pensar en recorrerlo y procesarlo: extrayendo la información del mismo y modificándola o simplemente visualizando. En este caso es interesante hacerlo por el principio: el nodo raiz.
Para ete propósito, la función revXMLRootNode
(treeID
) devuelve la situación de este nodo único, a partir de la indicación de un árbol ya creado.
En nuestro ejemplo, se ha concretado en la siguiente forma:
on mouseUp put revXMLRootNode(fld "docID" ) into fld "nodeRail" end mouseUp
Aviso |
En el caso de un fichero con cabecera (el anterior no més que té lo de ?xml="1.0" ...) ??? Què pasa en eixe cas?. |
A partir de la localización de un nodo del árbol es posible seguir descendiendo en el mismo consultando los nodos hijos de aquel. La función revXMLFirstChild
(treeID
,parentNode
) devuelve la situación en el árbol del primero de los hijos de un nodo dad. Asó por ejemplo para obtener el primero de los hijos del nodo raiz se puede llevar a cabo de la forma siguiente:
on mouseUp put revXMLFirstChild(fld "docID", fld "nodeRail") into fld "primerFill" end mouseUp
Observese que se utilizan los valores guardados en los campos de texto que se van incluyendo para visualizar los valores obtenidos en cada paso. En este caso: el identificador del árbol y la situación del nodo raiz.
Para recorrer los nodos hermanos de uno dado, esto es situados en un punto cualquiera del árbol moverse entre los nodos que están al mismo nivel de profundidad respecto del nodo raiz, se utilizan dos funciones en función del sentido en que se desee realizar la exploración: a la derecha (el nodo hermano siguiente) o a la izquierda (el anterior)..
La función revXMLNextSibling
(XMLText
,siblingNode
) permite obtener la situación del nodo hermano anterior como se muestra en el siguiente fragmento de cçodigo.
on mouseUp put revXMLNextSibling(fld "docID", fld "primerFill" ) into fld "seguentFill" end mouseUp
Análogamente a la anterior, para moverse en el otro sentido se utiliza la función revXMLPreviousSibling
(XMLText
,siblingNode
) que devuelve una cadena de caracteres donde se describe la situación de este nodo hermano.
En nuestro ejemplo, se ha concretado en la siguiente forma:
on mouseUp put revXMLPreviousSibling(fld "docID", fld "seguentFill" ) into fld "fillAnterior" end mouseUp
Si en el recorrido del árbol se hace necesario subir un nivel, en cualquier nodo del mismo, se ha de hacer uso de la función revXMLParent
(XMLText
,childNode
) que obtiene la situación del nodo padre, respecto al nodo hijo indicado. Así lo muestra este código:
on mouseUp put revXMLParent(fld "docID", fld "seguentFill") into fld "nodePare" end mouseUp
En el caso del nodo raiz, se devuelve la cadena vacía.
Para ...
La función revXMLAttribute
(XMLText
,parseBadData
,createTree
,sendMessages
) devuelve ...
En nuestro ejemplo, se ha concretado en la siguiente forma:
on mouseUp put fld "primerFill" & "/name [language] ="&& \ revXMLAttribute( fld "docID", fld "primerFill" & "/name", "language" ) into \ fld "atribut" end mouseUp
La función revXMLAttributes
(XMLText
,parseBadData
,createTree
,sendMessages
) devuelve un valor númerico que es utilizado para referirse al árbol que ha creado, con las particularidades que indican sus parámetros.
on mouseUp put empty into atributs repeat for each line thisLine in \ revXMLAttributes( fld "docID", fld "primerFill" & "/name", "=" & quote, quote ) put thisLine & ", " after atributs end repeat put ("Atributs de " & fld "primerFill" & "/name:" & return & atributs) into fld "atributs" put ("Atributs de " & fld "primerFill" & "/name son:" & return & atributs) end mouseUp
Hemos hablado que los documentos XML se guardan internamente como árboles para hacer posible un recorrido eficiente y de cómo estos árboles se nombran mediante identificadores (numéricos) que asignan las llamadas que utilizamos. En este apartado se exponen las que hacen posible averiguar cuáles hay y liberar esos identificadores cuando ya no son necesarios.
La función revXMLTrees
(XMLText
,parseBadData
,createTree
,sendMessages
) devuelve un valor númerico que es utilizado para referirse al árbol que ha creado, con las particularidades que indican sus parámetros.
En nuestro ejemplo, se ha concretado en la siguiente forma:
on mouseUp put empty into atributs repeat for each line thisLine in revXMLTrees() put thisLine & ", " after atributs end repeat put ("Arbres actius:" & return & atributs) into fld "deleteXMLTree" end mouseUp
La función revDeleteXMLTree
(XMLText
,parseBadData
,createTree
,sendMessages
) devuelve un valor númerico que es utilizado para referirse al árbol que ha creado, con las particularidades que indican sus parámetros.
on mouseUp revDeleteXMLTree fld "docID" put the result into fld "deleteXMLTree" end mouseUp
La orden revDeleteAllXMLTrees ???.
on mouseUp revDeleteAllXMLTrees put the result into fld "deleteXMLTree" end mouseUp Removes all XML tree structures in memory. revDeleteAllXMLTrees
Para ...
La función revXMLChildNames
(XMLText
,parseBadData
,createTree
,sendMessages
) devuelve ...
En nuestro ejemplo, se ha concretado en la siguiente forma:
on mouseUp put revXMLChildNames( fld "docID", "/", space, empty, true ) &\ return &\ revXMLChildNames( fld "docID", "/", space, empty, false ) into fld "nomFills" end mouseUp
La función revXMLChildContents
(XMLText
,parseBadData
,createTree
,sendMessages
) devuelve ...
En nuestro ejemplo, se ha concretado en la siguiente forma:
on mouseUp put revXMLChildContents( fld "docID", fld "primerFill", space, space, false, 0 ) put revXMLChildContents( fld "docID", fld "primerFill", space, space, true, 0 ) into \ fld "contingutFills" end mouseUp
Para ...
La función revXMLNodeContents
(XMLText
,parseBadData
,createTree
,sendMessages
) devuelve ...
En nuestro ejemplo, se ha concretado en la siguiente forma:
on mouseUp put revXMLNodeContents( fld "docID", fld "primerFill" & "/name" ) into \ fld "contingutFills" end mouseUp
[1] | Como la estructura de un sistema de ficheros, de hecho utilizaremos la nomenclatura más extendida en este campo para nombrar los nodos que lo conforman. |
[2] | Una pequeña nota al respecto de los términos utilizados como etiquetas: endangered_species significa "en peligro" (de extinción, en este caso), threat significa amenaza y poachers son "cazadores furtivos" |