XForms/Listas de Selección a partir de archivos

De Wikilibros, la colección de libros de texto de contenido libre.

Motivacion[editar]

Las personas que diseñan formularios frecuentemente tienen que mantener muchas tablas de código. dichas tablas de código pueden cambiar frecuentemente o puede haber también procesos de actualización de bases de datos centralizadas. Así que quieres que cada formulario dinámicamente obtenga el contenido de datos de un archivo XML o de un servicio web.

Este programa de ejemplo demuestra cómo leer una lista de códigos con etiquetas directamente de un archivo o servicio web. En este ejemplo el archivo que contiene los códigos es simplemente un archivo XML bien formado en el mismo directorio que el formulario.

Enlace a la aplicación funcionando[editar]

Nota: no soy el autor original de este ejemplo solamente lo tomo con fines ilustrativos.
Lista de selección a partir de archivos

Cargando una instancia de XML de un archivo local o un servicio web[editar]

El siguiente fragmento de código usualmente ubicado en la etiqueta HTML "head", demuestra cómo leer datos XML desde un archivo en el mismo directorio que el formulario usando el atributo "src" de la instancia.

Cargando una tabla de código simple a una instancia simple[editar]

<html>
   <xf:model>
      <xf:instance src="XMLSchemaTypeCode.xml" id="XMLSchemaTypeCode"/>
   </xf:model>
</html>

Cargando datos de un servicio web[editar]

Es común tener en un solo servicio cargadas todas las tablas de datos. A este servicio se le pueden pasar parámetros tales como el nombre de la tabla de datos, así como una persona es parte de un grupo. Esto puede reducir la lista de opciones para listas largas.

<html>
   <xf:model>
      <xf:instance id="ApprovalCodes" src="/db/mdr/services/all-codes.xq?code=ApprovalCodes&group=editor"/>
   </xf:model>
</html>

Cargando todos los datos en una sola instancia[editar]

El problema de cargar códigos individualmente en instancias individuales es que debes realizar un get HTTP por cada una de las tablas de datos. Esto no es un problema para formularios con una o dos listas de selección pequeñas. Pero para formularios largos con muchas listas de selección estos get pueden retrasar el tiempo de respuesta del formulario. La solución es cargar todas las tablas en una sola instancia con una sola solicitud get HTTP. Cada tabla de datos puede ser entonces seleccionada de esta instancia.

<html>
   <xf:model>
      <xf:instance src="/db/mdr/services/all-codes.xq?form=DataElementManager&group=admin"/>
   </xf:model>
</html>

En este segundo ejemplo todos los datos en el formulario completo estan siendo generados por un sevicio del Registro de Metadatos (MDR por la sigla en inglés). Los datos retornados por este servidor son una colección de códigos para cada control de selección del formulario.

Esto buscará por un archivo XML bien formado en el directorio actual y lo cargará en la instancia del modelo.

Nótese que en este caso al modelo se le da un id. Esto es necesario para permitir que múltiples tablas de datos sean leídas en su propio y separado modelo.

Previsualización[editar]

El usuario selecciona el valor de la lista desplegable. El valor en la salida es actualizado inmediatamente.

Notese que la etiqueta en la imagen no es la misma que en el esquema.

Programa ejemplo[editar]

<html
  xmlns="http://www.w3.org/1999/xhtml"
  xmlns:xf="http://www.w3.org/2002/xforms" >
   <head>
      <title>Select List From File</title>
 
      /* the default model */
      <xf:model>
         <xf:instance xmlns="">
            <MyData>
                  <MyXMLSchemaTypeCode/>
            </MyData>
         </xf:instance>
      </xf:model>
 
      /* read the codes from an external file into this model */
      <xf:model id="XMLSchemaTypeCode">
         <xf:instance src="XMLSchemaTypeCode.xml"/>
      </xf:model>
 
   </head>
   <body>
      <p>This selection list was read from a file.</p>
      <xf:select1  ref="/MyData/MyXMLSchemaTypeCode">
         <xf:label>Select XML Schema data type: </xf:label>
         <xf:itemset model="XMLSchemaTypeCode" nodeset="/XMLSchemaTypeCode/item">
            <xf:label ref="label"/>
            <xf:value ref="value"/>
         </xf:itemset>
      </xf:select1>
      <br />
      <xf:output ref="/MyData/MyXMLSchemaTypeCode">
         <xf:label>Value of MyXMLSchemaTypeCode: </xf:label>
      </xf:output>
   </body>
</html>

Ejemplo de datos[editar]

<?xml version="1.0" encoding="UTF-8"?>
<XMLSchemaTypeCode>
   <label>XML Schema Type:</label>
   <item>
      <label>Date and Time</label>
      <value>dateTime</value>
   </item>
   <item>
      <label>Time (HH:MM:SS-06:00)</label>
      <value>time</value>
   </item>
   <item>
      <label>Date (yyyy-mm-dd)</label>
      <value>date</value>
   </item>
   <item>
      <label>Year and Month</label>
      <value>gYearMonth</value>
   </item>
   <item>
      <label>Year (nnnn)</label>
      <value>gYear</value>
   </item>
   <item>
      <label>Month and Day</label>
      <value>gMonthDay</value>
   </item>
   <item>
      <label>Day of Month (1 .. 31)</label>
      <value>gDay</value>
   </item>
   <item>
      <label>Month (1 .. 12)</label>
      <value>gMonth</value>
   </item>
   <item>
      <label>String</label>
      <value>string</value>
   </item>
   <item>
      <label>Boolean (true/false)</label>
      <value>boolean</value>
   </item>
   <item>
      <label>Base 64 Binary</label>
      <value>base64Binary</value>
   </item>
   <item>
      <label>Decimal (0.00)</label>
      <value>decimal</value>
   </item>
   <item>
      <label>Any URI</label>
      <value>anyURI</value>
   </item>
   <item>
      <label>Integer (...,-2,-1,0,1,2,...)</label>
      <value>integer</value>
   </item>
   <item>
      <label>Non-Positive Integer (...,-2,-1,0)</label>
      <value>nonPositiveInteger</value>
   </item>
   <item>
      <label>Negative Integer (...,-2,-1)</label>
      <value>negativeInteger</value>
   </item>
   <item>
      <label>Long (-9,223,372T .. 9,223,372T)</label>
      <value>long</value>
   </item>
   <item>
      <label>Int (-2,147,483,648 .. 2,147,483,647)</label>
      <value>int</value>
   </item>
   <item>
      <label>Short (-32,768 .. 32,767)</label>
      <value>short</value>
   </item>
   <item>
      <label>Byte (-128 .. 127)</label>
      <value>byte</value>
   </item>
   <item>
      <label>Non-negative Integer (0..N)</label>
      <value>nonNegativeInteger</value>
   </item>
    <item>
      <label>Positive Integer (1..N)</label>
      <value>positiveInteger</value>
   </item>
   <item>
      <label>Unsigned Long (0 .. 18,446,744T)</label>
      <value>unsignedLong</value>
   </item>
   <item>
      <label>Unsigned Int (0 .. 4,294,967,295)</label>
      <value>unsignedInt</value>
   </item>
   <item>
      <label>Unsigned Short (0.. 65,535)</label>
      <value>unsignedShort</value>
   </item>
   <item>
      <label>Unsigned Byte (0..255)</label>
      <value>unsignedByte</value>
   </item>
</XMLSchemaTypeCode>

Extrayendo datos de un XML REST webservice[editar]

Se puede reemplazar el atributo src con una ruta directamente a un servicio web XML REST. por ejemplo, si se ponen todas las tablas de datos en los recursos de un proyecto, la ruta luciría como así:

<xf:instance src="../resources/code-tables/PersonGenderCode.xml"/>

o si los datos del sistemas están almacenados en un solo archivo XML y se tiene un wrapper XQuery or if your system codes are stored in a single XML file and you have a wrapper XQuery

<xf:instance src="../resources/code-tables/get-codes-for.xq?element=PersonGenderCode"/>

Listas de seleccion a partir de una sola instancia[editar]

para mantener los formulario rapidos, usualmente es mejor hacer una sola operacion HTTP GET para todos los datos. Los formularios que tienen varias listas de seleccion, tomaran mas tiempo para cargar si cada una de las listas realiza una operacion HTTP GET. Para grandes formularios es facil obtener una mejora de velocidad de 10x en tiempos de cargado.

Estructura de instacia de tablas de datos[editar]

El siguiente es un ejemplo de la estructura de todos los datos cargados en una sola instancia

<xf:instance id="code-tables">
   <code-tables>
      <code-table>
         <code-table-name>MyElementCode</code-table-name>
         <items>
            <item>
               <label>Joe Smith</label>
               <value>42</value>
            </item>
            <item>
               <label>Sue Johnson</label>
               <value>47</value>
            </item>
         <items>
      </code-table>
      <code-table>
         <code-table-name>ColorCode</code-table-name>
         <items>
            <item>
               <label>Red</label>
               <value>1</value>
            </item>
            <item>
               <label>Orange</label>
               <value>2</value>
            </item>
         <items>
      </code-table>
   </code-tables>
</xf:instance>

Ejemplo Select1[editar]

una vez los datos están cargados en el modelo, cada uno de los controles de select pueden obtener sus datos directamente desde el modelo usando el elemento <xf:itemset>. Itemset trabaja igual que Repeat y usa nodeset (no usa ref) para obtener todos sus valores. Acá hay un ejemplo de como obtener el conjunto de datos desde la instancia de tabla de datos.

<xf:select1 ref="instance('save-data')/MyElementName">
   <xf:label>My Element:</xf:label>
   <xf:itemset nodeset="instance('code-tables')/code-table[code-table-name='MyElementCode']/items/item">
       <xf:label ref="label"/>
       <xf:value ref="value"/>
   </xf:itemset>
</xf:select1>

Notese que el predicado [code-table-name='MyElementCode'] pondra unicamente los elementos para ese código en la lista de selección.