sábado, 14 de agosto de 2010

Algoritmos de Ordenación


Hace mucho tiempo que no escribía un entrada en este blog, la verdad la jornada laboral me consume todo el tiempo, asique cansado, pero a la vez contento porque mi memoria de título(Primer Post) a sido seleccionada para exposición oral en dos congresos internacionales mas: CITIC 2010 y JIISIC 2010.
Este post, trata de distintos tipos de algoritmos de ordenación, los típicos que vemos en la universidad, asique me pareció buena idea, publicar esta entrada como guía. Eh implementado cada algoritmo en un programa escrito en lenguaje C, por lo tanto, como siempre, si quieren el programa sólo tienen que pedirlo.

Ordenación por Selección: Este algoritmo es muy sencillo y funciona de la siguiente forma: se busca el elemento más pequeño del Vector y se intercambia con el que esta en la primera posición, después se busca el segundo mas pequeño y se intercambia con el elemento de la segunda posición y continua así hasta que el vector este ordenado.
Ejemplo:

Se ubica el elemento más pequeño del vector
5 10 8 1 9


Se intercambia con el que esta en la primera posición
1 10 8 5 9



Luego se ubica el segundo elemento más pequeño y se intercambia con el de la segunda
Posición
1 10 8 5 9


1 5 8 10 9


.
.
1 5 8 9 10

Así hasta quedar completamente ordenado.

El Algoritmo de este método es:
El bucle for hace referencia al intercambio de n veces del vector, y la variable i guarda la posición a intercambiar
for (i = 1; i <= n; i++)
{
el bucle while encuentra el elemento menor del vector que corresponde y se almacena en la variable min y la posición del elemento en la variable j
while (j<=n)
{
if (a[j] <= min)
{min = a[j]; pos = j ;}
j++;
}
hace el intercambio correspondiente con el menor encontrado
a [pos]=a[i];
a[i] =min;
j = i + 1;
min = 1000000;
}




Ordenación por Inserción: Este método funciona de la siguiente forma: el elemento considerado se inserta moviendo una posición a la derecha a todos los elementos mayores que el e insertando a continuación el elemento en la posición vacante.
Ejemplo:

Se compara la posición 2 con el 1 y se intercambia si es menor
5 6 8 1 9



Luego se compara la posición 3 con la 2
5 6 8 1 9


Luego la posición 4 con la 3, como la posición 4 es menor que la posición 3 entonces se intercambia sucesivamente hasta quedar ordenado
5 6 8 1 9

Se mueven todos los elementos mayores a la derecha
_ 5 6 8 9

Y se inserta el elemento en la posición correspondiente
1 5 6 8 9









El algoritmo de este método es:
a[0]=0; // elemento menor posible del vector
El bucle for hace referencia al ciclo de n-1 veces del método
for (i = 2; i< = n; i++)
{
j = i;
la variable var almacena el valor correspondiente a evaluar
var = a [i];
el ciclo while mueve todos los valores mayores que var a la derecha
while (a [j-1]>=var)
{
a[j] = a [j-1]; // intercambio
j--;
}
a[j]=var;
}


Método de Ordenación de Burbuja: En este método se efectúan tantos pasos en el Vector como sea necesario, intercambiando elementos adyacentes entre si, cuando en algún paso no se necesite intercambios el vector estar ordenado.
Ejemplos:
Compara la 2 posición con la 1, si esta es menor se intercambian
5 8 6 1 9

Luego se compara la 3 posición con la 2, y se intercambian
5 6 8 1 9

Luego se compara la 4 posición con la 3, y se intercambian
5 6 1 8 9

Luego se compara la n posición con la n-1 y si es menor se intercambian
5 6 1 8 9

Este procedimiento se hace n-1 veces hasta que el vector este completamente ordenado.
El algoritmo para este método es:
El bucle for hace referencia al ciclo de n-1 veces del método
for (i = 1; i<= n-1; i++)
{
este bucle for compara y ordena todos los elementos adyacentes entre sí , esto se repite
n-1 veces gracias al primer bucle for quedando el vector completamente ordenado
for (j = 1; j <n; j++)
{
el if compara los elementos adyacentes y si es menor el de la izq se intercambia, la variable var almacena el valor a intercambiar
if (a[j] >= a [j + 1])
{var = a [j + 1];
a [j + 1] = a[j];
a[j] = var;
}
}
}
Método de Ordenación Shell: La idea de este método es reorganizar el archivo para que tenga la propiedad de que tomando todos los elementos h-ésimos se obtenga un Archivo ordenado, Entonces estará h-ordenado o sea esta constituido por h archivos ordenados independientes y entrelazados entre sí.
Ejemplo:
Este ejemplo muestra la operación de la ordenación Shell para incrementos decrecientes
De 13, 4, 1
En el primer paso se toma la primera posición y se compara con la posición 13, y si es menor se intercambia.
5 6 8 7 4 6 9 2 3 3 4 2 1

Intercambio
1 6 8 7 4 6 9 2 3 3 4 2 5

En el segundo paso la serie es de 4 por lo tanto se divide el vector en partes de a 4 se compara y se ordena hasta que estos elementos queden ordenados
1 6 8 7 4 6 9 2 3 3 4 2 5

1 5 9 13
1 6 8 7 3 6 9 2 4 3 4 2 5

Luego se analiza las posiciones 2, 6, 10
1 6 8 7 4 6 9 2 3 3 4 2 5

2 6 10
Se comparan y se ordenan
1 3 8 7 4 6 9 2 3 6 4 2 5

Luego se compara las posiciones 3, 7, 11: 4, 8, 12 respectivamente
1 3 4 7 4 6 8 2 3 6 9 2 5

3 7 11
1 3 4 2 4 6 8 2 3 6 9 7 5

4 8 12
En el 3 paso la serie es de 1 luego el vector se divide en n partes, Este ultimo paso es
El método de inserción con la ventaja que ningún elemento tiene que desplazarse muy lejos
1 3 4 2 4 6 8 2 3 6 9 7 5
1 3 4 2 4 6 8 2 3 6 9 7 5
1 2 3 4 4 6 8 2 3 6 9 7 5
1 2 2 3 4 4 6 8 3 6 9 7 5
1 2 2 3 3 4 4 6 8 6 9 7 5
1 2 2 3 3 4 4 6 6 8 9 7 5
1 2 2 3 3 4 4 6 6 7 8 9 5
1 2 2 3 3 4 4 5 6 6 7 8 9

Quedando la lista finalmente ordenada



El algoritmo de este método es:
Este for muestra el incremento de la serie (16, 10, 7,…., 3), con la variable h como indicador de los h subarchivos del vector.

for (h = 1; j <= n/9; h = 3*h+1);
Este for divide la variable h en 3

for (; h>0; h/=3)

la variable i del for indica la siguiente posición a comparar
for (i=h+1; i<=n; i+=1)
{
La variable v es la variable pivote
v = a[i]; j = i;
En este ciclo while se compara y se intercambian los valores con la variable pivote
while (j>h && a [j-h]>v)
{a [j]=a [j-h]; j - = h;}
a[j] =v;
}

Método de Ordenación Quicksort: Esta es probablemente la técnica más rápida conocida. Fue desarrollada por C.A.R. Hoare en 1960.Su funcionamiento es el siguiente.
Eliges un elemento de la lista. Puede ser cualquiera .Lo llamaremos elemento de división. Buscas la posición que le corresponde en la lista ordenada. Acomodas los elementos de la lista a cada lado del elemento de división, de manera que a un lado queden todos los menores que él y al otro los mayores. En este momento el elemento de división separa la lista en dos sublistas. Realizas esto de forma recursiva para cada sublista mientras éstas tengan un largo mayor que 1. Una vez terminado este proceso todos los elementos estarán ordenados.
Comenzamos con la lista completa. El elemento divisor será el 4:
5 3 7 6 2 1 4

Comparamos con el 5 por la izquierda y el 1 por la derecha.
5 3 7 6 2 1 4

5 es mayor que cuatro y 1 es menor. Intercambiamos:
1 3 7 6 2 5 4

Avanzamos por la izquierda y la derecha:
1 3 7 6 2 5 4

3 es menor que 4: avanzamos por la izquierda. 2 es menor que 4: nos mantenemos ahí.
1 3 7 6 2 5 4

7 es mayor que 4 y 2 es menor: intercambiamos.
1 3 2 6 7 5 4

Avanzamos por ambos lados:
1 3 2 6 7 5 4

En este momento termina el ciclo principal, porque los índices se cruzaron. Ahora intercambiamos a[i] con a [der]
1 3 2 4 7 5 6

Aplicamos recursivamente a la sublista de la izquierda. Tenemos lo siguiente:
1 3 2

1 es menor que 2: avanzamos por la izquierda. 3 es mayor: avanzamos por la derecha. Como se intercambiaron los índices termina el ciclo. Se intercambia lista[i] con lista[sup]:
1 2 3

Al llamar recursivamente para cada nueva sublista (lista[0]-lista[0] y lista[2]-lista[2]) se retorna sin hacer cambios (condición 5.).Para resumir te muestro cómo va quedando la lista:
Segunda sublista: a [4] - a [6]
7 5 6

5 7 6

5 6 7

Para cada nueva sublista se retorna sin hacer cambios (se cruzan los índices).
Finalmente, al retornar de la primera llamada se tiene el arreglo ordenado:
1 2 3 4 5 6 7

El algoritmo para este método es:
Este if verifica que no se crucen los límites

if (der>izq)
{
la variable v contiene el valor de la partición
v = a [der]; i = izq-1; j = der;
for (;;)
{
Se clasifican los subarchivos
while (a [++i] <v);
while (a [--j]>v);

Sale del bucle cuando se Cruzan los punteros

if (i>=j) break;
Se intercambia los valores del vector
var = a[i]; a[i] = a[j]; a[j] = var;
}
Se ordena recursivamente los dos subarchivos, con el método divide y vencerás
var = a[i]; a[i] = a [der]; a [der] = var;
quicksort (izq, i-1);
quicksort (i+1, der);
}
Método de Ordenación por Residuo: En este método se aprovecha el hecho de que las claves pueden considerarse como números de algún intervalo finito, este tipo de métodos de ordenación se denominan ordenación por residuos. Este método funciona de la siguiente manera, se reordenan los registros de un archivos de manera que todas aquellas claves que comiencen con el Bit 0 se coloquen delante de todas las que comiencen con el Bit 1, para esto se examina el archivo empezando por la izquierda para encontrar una clave que empiece con el Bit 1 y empezando por la derecha para encorar una clave que empiece con el Bit 0, intercambiándolas recursivamente y continuando así hasta que se crucen los punteros.
Ejemplo:
La tabla esta inicialmente desordenada
9 = 1 0 0 1
6 = 0 1 1 0
7 = 0 1 1 1
2 = 0 0 1 0
8 = 1 0 0 0
10 = 1 0 1 0
1 = 0 0 0 1
5 = 0 1 0 1
4 = 0 1 0 0
3 = 0 0 1 1

Se Analiza el Bit mas izquierdo de los números y se ordena
6 = 0 1 1 0
7 = 0 1 1 1
2 = 0 0 1 0
1 = 0 0 0 1
5 = 0 1 0 1
4 = 0 1 0 0
3 = 0 0 1 1
9 = 1 0 0 1
8 = 1 0 0 0
10 = 1 0 1 0

Luego se ordena de la misma manera con el Bit que sigue, dejando los 1 hasta el principio del Bit 0 ordenado anteriormente
2 = 0 0 1 0
1 = 0 0 0 1
3 = 0 0 1 1
6 = 0 1 1 0
7 = 0 1 1 1
5 = 0 1 0 1
4 = 0 1 0 0
9 = 1 0 0 1
8 = 1 0 0 0
10 = 1 0 1 0

Luego se ordena el siguiente Bit
1 = 0 0 0 1
2 = 0 0 1 1
3 = 0 0 1 1
5 = 0 1 0 1
4 = 0 1 0 0
6 = 0 1 1 0
7 = 0 1 1 1
9 = 1 0 0 1
8 = 1 0 0 0
10 = 1 0 1 0

Finalmente se ordena el primer Bit de los elementos, quedando la tabla ordenada
1 = 0 0 0 1
2 = 0 0 1 1
3 = 0 0 1 1
4 = 0 1 0 0
5 = 0 1 0 1
6 = 0 1 1 0
7 = 0 1 1 1
8 = 1 0 0 0
9 = 1 0 0 1
10 = 1 0 1 0

El algoritmo de este método es:
Este if verifica que no se crucen las variables izq y der

if (der > izq && b > 0)
{
Las variables i y j toman los valores limites
i = izq; j = der;
while (j != i)
{
Estos ciclos while compara los bits de los datos del vector
while (! c[i].bits (b, 1) && i < j) i++;
while (c[j].bits (b, 1) && j > i) j--;
Intercambia los valores
Intercambio (i, j);
}
Este if aumenta j si c[der].bit es falso o sea si no ha llegado al limite
if (!c[der].bits(b,1)) J++;

Llama recursivamente a la función residuos
residuos (izq, j-1, b-1);
residuos (j, der, b-1);
}

jueves, 25 de febrero de 2010

Simulación de Estados de Procesos

Introducción

En los procesadores multiprocesos se pueden distinguir 4 estados principales (listo, bloqueado, suspendido y nuevo).

En ese post se analiza los 4 estados de los procesos en el cual se detalla su descripción como ejemplo de uso y análisis del funcionamiento del sistema operativos multiprocesos.

Además un programa en código C que emula el funcionamiento de los estados de los procesos, si quieren la fuente de este programa, sólo tienen que pedirlo...

clip_image002

Estructura de Datos: Los cuatro estados que puede tener un proceso son: nuevo, listo, suspendido, bloqueado cada estado representa una cola única, y estas se manejan a través de una lista enlazada, por tanto se crea una estructura Nodo y una estructura lista a través de los TAD correspondientes, el código es el siguiente.

Estructura de los Nodos

typedef struct ListaNodo

{

int info;

struct ListaNodo *ant, *sig;

} *pListaNodo,ListaNodo;

typedef struct Estructura de las Listas

{

pListaNodo primero, ultimo, ventana;

int longitud;

} TLista, *Lista;

typedef pListaNodo Ventana;

además se crean varias funciones de implementación de la estructura como iniciar lista, anexar lista , primer lista, ultimo lista , siguiente lista, etc., estas funciones están implementadas en la cabecera tadlista.h

Colas: Para el manejo de las colas se crea una cabecera colas.h, la cual ocupa la lista enlazada y generando nuevas funciones para la implementación de la cola, para ello se crea una variable tipo lista de nombre cola.

typedef Lista Cola;

Luego se crean varias funciones de implementación como iniciar Cola, Vaciar Cola, información de la Cola, etc.

Veamos algunos Ejemplos:

La función adicCola sitúa un nuevo elemento de la cola al final de ésta

void adicCola( Cola col, int elem )

{

ultLista(col);

anxLista(col,elem);

}

La función elimCola elimina el primer elemento de la cola

void elimCola( Cola col )

{

primLista(col);

elimLista(col);

}

int longCola( Cola col ) Retorna la longitud de la cola

{

return col->longitud;

}

Estas funciones son muy importantes para facilitar el manejo de las colas y para el buen funcionamiento del programa.

Estructura del Proceso: cada proceso es una estructura con sus propias variables y a cada

Proceso se le asigna una letra única de identificación, los procesos poseen un valor, una linea de instrucción, un estado y una dirección de memoria.

Cada proceso puede tener un máximo de 10 líneas de instrucción y le corresponde una única dirección de memoria de 10 espacios la cual posee en toda su vida activa

El código de la estructura de los procesos es el siguiente

typedef struct est_procesos

{

int n; Valor del proceso

int linea[10]; linea de instrucción

int bcp; dirección del bcp

char estado; estado del proceso

int mem; linea de memoria asignada

} tproceso,*proceso;

Crear proceso: esta función se encarga de crear un proceso e inicia sus valores iniciales

Cada proceso creado se guarda en un vector de procesos PRO [] este vector es muy importante por que sirve para guardar todos los procesos creados y permite al programa recoger información de un proceso en cualquier momento, los valores del proceso es también su dirección en este Vector

proceso crear_proceso(int n,int l,int memoria)

{

Proceso A; Crea el proceso

A = (proceso) malloc (sizeof (tproceso)); asigna memoria

A->n = 1; valor del proceso

A=vaciar_linea(A);

A->linea[l]=1; linea de instrucción leída

A->estado='n'; estado nuevo

A->mem=memoria; espacio de dirección asignada

return A; retorna el proceso al vector PRO[]

}

Asignación de memoria: Cada proceso tiene asignada una porción de porción de memoria fija de 10 celdas y solo puede ocupar esa parte de la memoria

int memoria [200]; este vector simula la memoria del computador en total puede almacenar 20 porciones de memoria para 20 procesos, por ejemplo un proceso X puede tomar una celda de [10 -19]

Para garantizar que este espacio de memoria sea único para cada proceso se encuentra la función vacio_mem.

La variable mem es una dirección aleatoria de memoria, si esta libre el espacio de memoria retornara la misma dirección, en caso que la dirección esté ocupada buscara la próxima dirección siguiente vacía.

El vector Vacio [] se encarga de almacenar las direcciones no ocupadas

mem=vacio_mem(mem,dato); la función vacio_mem retornara la dirección de memoria a

La variable mem que más tarde se le asignara al proceso

Correspondiente.

int vacio_mem(int n,int dato)

{

int i;

if(memoria[n]==0)

{

memoria[n]=dato; si la memoria no esta asignada retorna la misma

Dirección

return n;

}

else

{

for(i=1;i<=20;i++) En caso contrario busca un espacio de memoria

Vacía

{

if(vacio[i]==0)

{

vacio[i]=dato;

return i*10;

}

}

}

Return 0; en el caso que no haya memoria disponible

Retornara un valor cero

}

Estados del proceso:

Nuevo: es la cola donde se alojan los procesos que se van generando aleatoria mente

clip_image004

Listo: Son los procesos que interactúan con el procesador y lo hacen hasta terminar sus

Instrucciones

clip_image006

Bloqueado: son los procesos que solicitan un recurso de Entrada y salida

clip_image008

Suspendidos: Son los procesos que no tienen asignada una dirección de memoria

clip_image010

Planificador: Una vez cargados todos los procesos a la cola de tipo nueva se pone en marcha la función Planificador, La función planificador se encarga de de seleccionar el proceso que pasara de su estado nuevo a listo, dependiendo de la antigüedad del proceso, siendo seleccionado el proceso a través de una política FIFO (primero que entra primero que sale)

Aquí llama a la función planificador y retornara a la cola listo

listo=planificador(nuevo,listo);

Lista planificador(Lista col,Lista cola)

{

proceso proces;

proces=pro[infoCola(col)]; se recupera el proceso a través del vector PRO []

Confirma que tiene memoria seleccionada

if(proces->mem!=0)

{

primLista(col); primero de la lista

adicCola(cola,infoCola(col)); adiciona a la cola listo

elimCola(col); elimina el proceso de la cola nuevo

flechas();

}

Return cola; retorna la cola a la cola listo

}

Suspendor: esta función se encarga de seleccionar el proceso que no tiene memoria y lo pasa a la cola de estado suspendido.

Aquí llama a la función suspendor y se devuelve a la cola suspendida

suspendido= suspendor(nuevo,suspendido); procesos que no tienen asignada memoria

Lista suspendor(Lista col,Lista sus)

{

proceso proces;

proces=pro[infoCola(col)];

if(proces->mem==0) confirma que el proceso no tenga asignada

Memoria

{

primLista(col);

adicCola(sus,infoCola(col)); mueve el proceso a la cola de estado

Suspendido

ElimCola (col);

}

Bloqueador: esta función selecciona a los procesos que requieren recursos de entrada y salida y pasa el proceso de la cola listo a la cola de estado Bloqueado

Lista bloqueador(Lista col, Lista blo)

{

proceso proces;

proces=pro[infoCola(col)]; recupera el proceso

if(proces->linea[proces->n]==1) pregunta si es del tipo entrada

Salida (1)

{

adicCola(blo,infoCola(col)); pasa el proceso al estado

bloqueado

if(!vaciaCola(col))elimCola(col);

}

return blo; retorna la cola bloqueado

}

Procesador: el procesador se encarga de leer la linea de instrucción del proceso e incrementa en una unidad, solo es capaz de leer un proceso a la vez, y retorna el proceso al final de la cola tipo listo.

Cuando un proceso llega al límite de instrucción que son 10 instrucciones el proceso se elimina automáticamente liberando su memoria para poder ingresar otro proceso

proceso actualizar_proceso(proceso A) función de procesador que actualiza los

{ Datos del proceso

int j;

j=A->n;

j++;

A>n=j; aumenta en uno la instrucción del proceso

A->estado='l';

return A; retorna el proceso

}

Ejemplo:

clip_image012

Este ejemplo es un procesador ejecutando un proceso M

Informaciones Generales Sobre los procesos

En el programa se muestran dos recuadros que muestran toda la información sobre los procesos en ejecución, el recuadro estadística se muestra los valores que posee el proceso en el instante de su ejecución y el recuadro memoria muestra la porción de memoria asignada a ese proceso.

Cuadro Estadísticas: muestras los datos referentes a cada proceso en ejecución:

Proceso: Letra asignada

Instrucción: número de linea de la instrucción que se esta ejecutando

Linea [6] = tipo de instrucción o [E/S]. Si la instrucción no requiere ningún recurso

Externo, entonces se imprime Instruc. En caso de que requiera una

Instrucción [E/S] entonces se imprime [E/S] y el proceso pasaría a estado

Bloqueado.

Estado = muestra su estado listo

clip_image014

Memoria: muestra la porción de memoria asignada a cada proceso en ejecución, en este caso el proceso solo puede ocupar su porción de memoria de 10 celdas que es de 140 a 149

clip_image016

Políticas Generales del programa

En un sistema operativo se utilizan varias políticas de ejecución de sus tareas como es la asignación de memoria, el tipo de prio ridad de los procesos, etc. El uso de estas políticas define y afecta el comportamiento general del sistema.

En este programa se usan varios manejos de implementación para definir el comportamiento de los procesos como son las políticas de asignación de memoria o políticas de prioridad de los procesos.

Políticas sobre la memoria: se ha creado una memoria de 200 celdas de tamaño fijo, la cual puede albergar a 20 procesos activos, cada proceso tiene asignado 10 celdas de memoria y solo puede ocupar esa porción de memoria asignada.

Procesos

0

1

2

3

4

5

6

7

8

9

A

B

.

.

Y

Z

Políticas de Prioridad: Para el manejo de los procesos se ha asignado la prioridad FIFO

(First in First out), primero que entra primero que sale, por tanto los procesos mas antiguos en la cola son los primeros que se ejecutan en el procesador

clip_image017

Vista general del programa:

clip_image019

Conclusión

Este post ha tratado de los distintos estados que puede tener un proceso a lo largo de su ejecución, la simulación se ha realizado a través de un programa escrito en C++.

En el software de simulación se ha divido en un archivo con extensión CPP y 4 cabeceras header, la cual la cabecera interface contiene todas las interfaces del programa, las cabeceras cola.h y tadlista.h, contienen toda la estructura de datos del programa.

miércoles, 3 de febrero de 2010

Validar XML con XSD y VB.NET

En este post, explicaré como un documento XML es validado por un documento XSD y como a través de VB.NET puedo ocupar estos documentos para validar a traves de código.

Bueno empecemos...

El lenguaje XML es un lenguaje de marca muy parecido a un documento HTML, pero hay una diferencia principal y es que el HTML no indica lo que se está representando, tiene datos mal definidos con elementos de formato, mientras que el XML contiene datos que se autodefinen: describe el contenido de lo que etiquetan.

Veamos un ejemplo:

La primera linea sólo nos dice al version del XML y la codificación, esta linea es necesaria en todos los documentos XML.

Después tengo una etiqueta “Documento” con un atributo DocID, esta etiqueta es “compleja”, ya que tiene etiquetas dentro, en nuestro caso Nombre, por lo tanto, una etiqueta es compleja o simple, si tiene o no etiquetas dentro.

Ahora se nos hace necesario validar este docuemento, para ello utilizamos los archivos con extensión XSD.

Cabe aclarar que un documento puede estar bien formado y válido, bien formado es cuando su sintaxis es correcta, por ejemplo todas las etiquetas tienen sus respectivos cierres, y válido cuando pasar por la revisión del XSD.

Acá hay un xsd para el documento xml anterior:




OJO: “este XSD valida que solo exista una etiqueta nombre, si queremos que exista más de una etiqueta Nombre entonces hay que agregar en “element nombre”, el atributo “maxoccurs=10”, de esa manera podrán haber hasta 10 etiquetas Nombre”

La primera línea define el NameSpace, estos se utilizan para proporcionar a los elementos un nombre único, en este caso xsd Después hay una etiqueta element, que representa una etiqueta en un documento XML, en este caso el elemento es "Documento", como la etiqueta es compleja, osea tiene etiquetas dentro, entonces se escribe la linea complextype, para enumerar todas las etiquetas que tiene dentro, en este caso sólo es "Nombre", como "Nombre" es una etiqueta simple, no lleva esta etiqueta. La etiqueta sequence sirve para enumerar los elementos anidados.

Ahora como documentos tiene atributos estos se deben declarar con la etiqueta attribute, donde definimos el nombre, el uso si es requerido o no y el tipo de datos, si es número o texto. Esta etiqueta siempre va luego del cierre de la etiqueta sequence.

Para asociar un documento XML con un XSd se debe agregar una etiqueta xsi:noNamespaceSchemaLocation="DocIngreso.xsd"

Ahora lo más interesante, ¿cómo hago para que mi sistema valide mis documentos XML con los documentos XSD?.


Bueno muy facíl, dare un pequeño ejemplo en VB.NET, si quieren un ejemplo en otro lenguaje sólo tienen que pedirlo.

Ahi va..

Lo primero es importar las librerias necesarias

Imports System.Xml

Imports System.Xml.Schema

Sub Main()

Luego creamos un objeto XmlTextReader, este objeto es un lector de un documento XML

Dim tr As New XmlTextReader("c:\DocIngreso.xml")

Luego cramos un objeto XmlValidatingreader y lo asociamos al objeto XmlTextReader

Dim vr As New XmlValidatingReader(tr)

Abrimos el documento xsd

vr.Schemas.Add("", "c:\DocIngreso.xsd")

y lo validamos por tipo Schema que es el tipo XSD

vr.ValidationType = ValidationType.Schema

luego leemos el documento xml, si se produce un error lo capturamos, sino es porque el documento es valido

AddHandler vr.ValidationEventHandler, AddressOf ValidationHandler

While vr.Read()

End While

Console.WriteLine("Documento es válido")

Console.Read()

End Sub

Haber probemos el codigo!!!

El xsd me dice que el atributo DocID es un numero entero

Entonces probarpe con el DocId con un tipo numero y otro tipo texto.

Primer ejemplo con DocID=”123” (tipo numero)

Como era de esperarse el documento es válido según el xsd.

Segundo ejemplo con DocID=”alguna palabra” (tipo texto)

Acá nos sale el error y el mensaje, que el tipo de datos no es valido para el atributo DocID

Funciona!!!

Bueno espero les sirva…..

Aquí va el codigo completo...........................................

Imports System.Xml

Imports System.Xml.Schema

Module Module1

Sub Main()

Dim tr As New XmlTextReader("c:\DocIngreso.xml")

Dim vr As New XmlValidatingReader(tr)

vr.Schemas.Add("", "c:\DocIngreso.xsd")

vr.ValidationType = ValidationType.Schema

AddHandler vr.ValidationEventHandler, AddressOf ValidationHandler

While vr.Read()

End While

Console.WriteLine("Documento es válido")

Console.Read()

End Sub

Public Sub ValidationHandler(ByVal sender As Object, ByVal args As ValidationEventArgs)

Console.WriteLine("***Validation error")

Console.WriteLine("Severity:{0}", args.Severity)

Console.WriteLine("Message:{0}", args.Message)

Console.Read()

End Sub

End Module

Emprendedores: ¿Quién es tu cliente?

“Hay dos tipos de personas en el mundo: hay personas que inventan excusas, y hay empresarios” Hace poco termine de leer el libro  Disc...