Obtener acceso al nombre de los nodos
Cuando un nodo de un componente XML (o un campo de un componente CSV/FLF) tiene nodos secundarios, podemos obtener tanto el nombre como el valor de cada nodo secundario en la asignación directamente. Esta técnica se denomina nombres de nodo dinámicos. El adjetivo dinámicos hace referencia al hecho de que el procesamiento se realiza sobre la marcha, durante la ejecución de la asignación, y no se basa en la información estática del esquema que se conoce antes de que se ejecute la asignación. En este apartado explicamos cómo habilitar el acceso dinámico a nombres de nodo y cómo utilizarlo.
Cuando se leen datos de un componente de origen, los nombres de nodo dinámicos permiten:
•Obtener una lista de nodos o atributos secundarios de un nodo en forma de secuencia. En MapForce una secuencia es una lista de cero o más elementos que se pueden conectar con un componente de destino y que crea tantos elementos en el componente de destino como elementos existen en el componente de origen. Por ejemplo, si un nodo tiene cinco atributos en el componente de origen, puede crear cinco elementos nuevos en el componente de destino (cada uno de ellos corresponderá a un atributo).
•Leer no sólo los valores de los nodos secundarios (como hacen las asignaciones normales y corrientes) sino también sus nombres.
Cuando se escriben datos en un componente de destino, los nombres de nodo dinámicos permiten:
•Crear nodos nuevos usando nombres que vienen dados por la asignación (nombres dinámicos), en lugar de los nombres que vienen dados por la configuración del componente (nombres estáticos).
A continuación veremos un ejemplo basándonos en el esquema XML <Documentos>\Altova\MapForce2025\MapForceExamples\Tutorial\Products.xsd. Este esquema viene acompañado de un documento de instancia llamado Products.xml. Para agregar tanto el esquema como el archivo de instancia al área de asignación seleccione Insertar | Archivo o esquema XML y navegue hasta el archivo <Documentos>\Altova\MapForce2025\MapForceExamples\Tutorial\Products.xml. Cuando la aplicación solicite un elemento raíz, seleccione products.
Para habilitar los nombres de nodo dinámicos para el nodo product haga clic con el botón derecho en ese nodo y seleccione uno de estos comandos en el menú contextual:
•Mostrar atributos con nombre dinámico si desea tener acceso a los atributos del nodo o
•Mostrar elementos secundarios con nombre dinámico si desea tener acceso a los elementos secundarios del nodo.
Fig. 1: Habilitar nombres de nodo dinámicos (para elementos secundarios)
Nota: | Los comandos que aparecen en la imagen anterior solamente están disponibles cuando se trata de nodos con nodos secundarios. Además, estos comandos no están disponibles cuando se trata del nodo raíz. |
Cuando se cambia un nodo al modo dinámico, aparece un cuadro de diálogo como el de la imagen siguiente. Siguiendo con nuestro ejemplo, ahora configuramos las opciones que puede ver en la imagen (estas opciones se definen en detalle en el apartado Obtener acceso a determinado tipo de nodos).
Fig. 2: Cuadro de diálogo "Configuración de secundarios con nombre dinámico"
A continuación explicamos lo que hace el componente cuando se habilitan los nombres de nodo dinámicos para el nodo product. Observe que el aspecto del componente cambia significativamente.
Fig. 3: Nombres de nodo dinámicos habilitados (para elementos secundarios)
Para restaurar el modo estándar del componente haga clic con el botón derecho en el nodo product y desactive el comando Mostrar elementos secundarios con nombre dinámico en el menú contextual.
En la imagen siguiente podemos ver el aspecto que tiene el componente cuando se habilita el acceso dinámico a los atributos de un nodo (haciendo clic con el botón secundario en el elemento product y seleccionando el comando Mostrar atributos con nombre dinámico en el menú contextual).
Fig. 4: Nombres de nodo dinámicos habilitados (para atributos)
Para restaurar el modo estándar del componente haga clic con el botón derecho en el nodo product y desactive el comando Mostrar atributos con nombre dinámico en el menú contextual.
Como puede ver en las dos imágenes anteriores, el aspecto del componente cambia cuando se habilita el modo nombres de nodo dinámicos en uno de los nodos (en nuestro ejemplo se trata del nodo product). El nuevo aspecto del componente ofrece varias opciones nuevas porque permite:
•Leer o escribir una lista con todos los elementos secundarios o atributos de un nodo (que vienen dados por el elemento element() o attribute() respectivamente).
•Leer o escribir el nombre de cada elemento secundario o atributo (que viene dado por el elemento node-name() o local-name() respectivamente).
•Si se trata de elementos, leer o escribir el valor de cada elemento secundario, en el tipo de datos que corresponda. Este valor viene dado por el nodo de conversión de tipo (el elemento text()). Recuerde que solamente los elementos pueden tener nodos de conversión de tipo. Los atributos siempre tienen el tipo "string".
•Agrupar o filtrar elementos secundarios por nombre (véase Ejemplo: agrupar y filtrar nodos según su nombre).
A continuación explicamos con qué tipos de nodos puede trabajar cuando use el modo nombres de nodo dinámicos.
element()
Este nodo diferentes comportamientos, dependiendo de si está en el componente de origen o en el componente de destino. Si está en el componente de origen, aporta los elementos secundarios del nodo en forma de secuencia. En la Fig. 3 (ver más arriba) el elemento element() ofrece una lista (secuencia) con todos los elementos secundarios de product. Por ejemplo, la secuencia que se crea a partir de este XML contendría tres elementos (porque product tiene tres elementos secundarios):
<product> <id>1</id> <color>red</color> <size>10</size> </product> |
Observe que el nombre y el tipo de cada elemento de la secuencia es el que nos da el nodo node-name() y el nodo de conversión de tipo respectivamente. Imagine que necesita pasar datos de un archivo XML a otro XML de destino de la siguiente manera:
Fig. 6: Asignación entre nombres de elemento XML y valores de atributo
Para conseguir este objetivo debemos diseñar esta asignación de datos:
Fig. 7: Asignar nombres de elemento XML a valores de atributo
El papel que element() desempeña aquí es aportar la secuencia de elementos secundarios de product, mientras que node-name() y text() aportan el nombre y el valor real de cada elemento de la secuencia. Esta asignación se describe más detalladamente en el apartado Ejemplo: asignar nombres de elemento a valores de atributo.
En el componente de destino element() no crea nada por sí mismo, lo cual constituye una excepción de la regla básica de asignación (por cada elemento del origen, crear un elemento de destino). Los elementos propiamente dichos los crean los nodos de conversión de tipo (usando el valor de node-name()) y por los nodos de prueba de nombre (usando su propio nombre).
attribute()
Como puede verse en la figura nº4, este elemento permite acceder a todos los atributos del nodo en tiempo de ejecución de la asignación. En un componente de origen aporta, en forma de secuencia, los atributos del nodo de origen que está conectado. Por ejemplo, en este archivo XML, la secuencia incluiría dos elementos (porque product tiene dos atributos):
<product id="1" color="red" /> |
Observe que el nodo attribute() sólo aporta el valor de cada atributo en la secuencia, siempre como tipo string. El nombre de cada atributo viene dado por el nodo node-name().
En un componente de destino este nodo procesa una secuencia conectada y crea un valor de atributo por cada elemento de la secuencia. El nombre de atributo viene dado por node-name(). Por ejemplo, imagine que necesita pasar datos de un archivo XML a otro archivo XML de la siguiente manera:
Fig. 8: Asignar valores a nombres de atributo
Para conseguir este objetivo debemos diseñar esta asignación de datos:
Fig. 9: Asignar valores de atributo a nombres de atributo
Nota: | Esta transformación puede conseguirse sin habilitar el acceso dinámico a los atributos del nodo, pero aquí usamos el acceso dinámico para explicar cómo funciona attribute() en un componente de destino. |
Si quiere reconstruir esta asignación, tenga en cuenta que usa los mismos componentes XML que la asignación ConvertProducts.mfd de la carpeta <Documentos>\Altova\MapForce2025\MapForceExamples\Tutorial\. La única diferencia es que el destino ahora es el origen y el origen ahora es el destino. Como datos de entrada del componente de origen deberá utilizar una instancia XML que contenga valores de atributo, por ejemplo:
<?xml version="1.0" encoding="UTF-8"?> |
Nota: | Para simplificar el ejemplo se omitió la declaración de espacio de nombres y de esquema en el fragmento de código anterior. |
node-name()
En un componente de origen node-name() aporta el nombre de cada elemento secundario de element() o el nombre de cada atributo de attribute() respectivamente. Por defecto el nombre que aporta node-name() es de tipo xs:QName. Para obtener el nombre como tipo string debe utilizarse el nodo local-name() (véase la figura nº3) o utilice la función QName-as-string.
En un componente de destino node-name() escribe el nombre de cada elemento o atributo que exista en element() o attribute().
local-name()
Este nodo funciona igual que el nodo node-name(), pero su tipo es xs:string en lugar de xs:QName.
Nodo de conversión de tipo
En un componente de origen el nodo de conversión de tipo aporta el valor de cada elemento secundario que incluye element(). El nombre y la estructura de este nodo dependerá del tipo qeu esté seleccionado en el cuadro de diálogo "Configuración de secundarios con nombre dinámico" (figura nº2).
Para cambiar el tipo del nodo haga clic en el botón Cambiar selección y seleccione un tipo de la lista de tipos disponibles, incluido el comodín de esquema (xs:any). Consulte Obtener acceso a determinado tipo de nodos para obtener más información.
En un componente de destino el nodo de conversión de tipo escribe el valor de cada elemento secundario que incluye element(), en el tipo de datos correspondiente. El tipo de datos deseado se selecciona haciendo clic en el botón Cambiar selección .
Nodos de prueba de nombre
En un componente de origen los nodos de prueba de nombre permiten agrupar o filtrar elementos secundarios de una instancia de origen por nombre. Por ejemplo, si necesita filtrar elementos secundarios por nombre para que la asignación acceda a los datos de instancia usando el tipo correcto (véase Obtener acceso a determinado tipo de nodos). Para ver un ejemplo consulte Ejemplo: agrupar y filtrar nodos según su nombre.
En general los nodos de prueba de nombre funcionan casi igual que los nodos de elemento normales para leer y escribir valores y subestructuras. Sin embargo, como la semántica de la asignación es distinta cuando está habilitado el acceso dinámico, existen algunas restricciones. Por ejemplo, no se puede concatenar el valor de dos nodos de prueba de nombre.
En un componente de destino los nodos de prueba de nombre crean tantos elementos en el resultado como elementos existen en la secuencia de origen conectada. Su nombre reemplaza el valor que esté asignado a node-name().
Si es necesario, puede ocultar los nodos de prueba de nombre en el componente. Esto se hace haciendo clic con el botón Cambiar selección del nodo element() y desactivando la casilla Mostrar nodos de prueba.... en el cuadro de diálogo "Configuración de secundarios con nombre dinámico" (figura nº2).