Interprete de peticiones en lenguaje natural a un Web feature server de nombres geográficos

María Navas Tapiador 
Curso 2001-2002

1	Interrogación del Web Feature Server de datos geográficos del NIMA.
2	Modelo de datos
3	Reglas de reescritura
4	Funciones Lisp
4.1	Librerías utilizadas
4.2	Parsear GML
5	Futuras mejoras
6	Principales dificultades
A1 Especificación de la gramática
A2  Funciones LISP
A3 Ejemplos
1	Interrogación del Web Feature Server de datos geográficos del NIMA.

El intérprete de lenguaje natural se encargará de recoger una petición realizada al Web Feature Server, que contiene datos geográficos pertenecientes al NIMA, traducirla a una petición http creando el filtro adecuado, y devolver el resultado de la petición. Los “features” que devuelve este servidor son una serie de puntos que representan distintos elementos geográficos de interés(ríos, ciudades, montañas, etc...). Los tipos de peticiones que se han considerado pueden dividirse en dos grandes grupos: petición de features en general o petición de un tipo concreto de features (administrativas, hidrológicas, carreteras, etc...). Para cada uno de estos dos tipos de peticiones, se han considerando las siguientes preguntas:
•	Preguntas a través del nombre.
•	Preguntas a partir de ciertas características del nombre (empieza por, acaba por, contiene la cadena...).
•	Preguntas por país.
•	Preguntas por los elementos a cierta distancia de uno dado.

También es importante destacar que aunque el número de features puede no limitarse, en principio se ha limitado a 20 features  para evitar problemas de prestaciones.
 
También se ha aprovechado la infraestructura de frames, para almacenar en ella el resultado de las peticiones al servidor. Esto permite minimizar el número de peticiones, ya que sólo se realizarán si lo que se busca no está ya almacenado en un frame.  Por ejemplo, si yo estoy buscando Juslibol, pero no estoy seguro del nombre, preguntaré por los pueblos que empiezan por Jus. Si más adelante quiero saber que ríos están cerca de Juslibol,  ya no tendré que hacer una pregunta para obtener las coordenadas geográficas de Juslibol (y con ellas crear el filtro espacial), sino que esa información la obtendré del frame correspondiente.
2	Modelo de datos 
La jerarquía de clases que se ha utilizado, se muestra en el siguiente modelo. La clase feature-type hace referencia al tipo de features que nos podemos encontrar, siendo  instancias de esta clase feature-type, features administrativos, hidrográficos, carreteras, lugares, etc... 

;*********************************************************************
; Módulo: NIMA
; Uso:    Modelo de datos del NIMA
; Autor:  María Navas Tapiador
; email:  mnavas@ebro.cps.unizar.es
;*********************************************************************

(defun nima ()
   (let ()	 (base-form 'objeto)
      (form :name 'feature :is-a 'type-feature :slots (list '(featureDesignation) '(country) '(nameType) '(latitud) '(longitud)))
      (form :name 'pais :is-a 'objeto :slots (list '(siglas)))
      (form :name 'type-feature :is-a 'objeto :slots (list '(fc)))
      (form :name 'distance :is-a 'objeto :slots (list '(degrees)))
      (form :name 'distance-max :is-a 'distance)
    
      (form :name 'Administrative :is-a 'type-feature)
      (set-value 'Administrative 'fc 'A)

      (form :name 'Hydrographic :is-a 'type-feature)
      (set-value 'Hydrographic 'fc 'H)

      (form :name 'Area :is-a 'type-feature)
      (set-value 'Area  'fc 'L)

      (form :name 'Place :is-a 'type-feature)
      (set-value 'Place 'fc 'P)

      (form :name 'Road :is-a 'type-feature)
      (set-value 'Road 'fc 'R)

      (form :name 'Spot :is-a 'type-feature)
      (set-value 'Spot  'fc 'S)

      (form :name 'Hypsographic :is-a 'type-feature)
      (set-value 'Hypsographic  'fc 'T)

      (form :name 'Udrsea :is-a 'type-feature)
      (set-value 'Udrsea  'fc 'U)

      (form :name 'Vegetation :is-a 'type-feature)
      (set-value 'Vegetation  'fc 'V)

      (form :name 'Andorra :is-a 'pais)
      (set-value 'Andorra 'siglas 'AN)
      (form :name 'France :is-a 'pais)
      (set-value 'France 'siglas 'FR)
      (form :name 'Gibraltar :is-a 'pais)
      (set-value 'Gibraltar 'siglas 'GI)
      (form :name 'Morocco :is-a 'pais)
      (set-value 'Morocco 'siglas 'MO)
      (form :name 'Portugal :is-a 'pais)
      (set-value 'Portugal 'siglas 'PO)
      (form :name 'Spain :is-a 'pais)
      (set-value 'Spain 'siglas 'SP)
      (form :name 'Vatican :is-a 'pais)
      (set-value 'Vatican 'siglas 'VT) ))

3	Reglas de reescritura
Se utilizan varias reglas de reescritura con el fin de utilizar un número reducido de reglas para reconocer una amplia gama de palabras. Las reglas que se han considerado son:

•	Paso de minutos a grados. 
•	Paso de  diferentes tipos de features al tipo genérico que es capaz de distinguir el Web Feature Server.

<administratives> -> (administrative divisions | political entities)
<hydrographics> -> (bays | lakes | seas | rivers | oceans |ponds)
<areas> -> (areas | coasts | republics | regions | reserves)
<places> -> (places | villages | cities )
<roads> -> (roads | railroads | tunels)
<spots> -> (interesting places | stations | spots)
<hypsographics> -> (beachs | cliffs | deltas |depressions | dessert)
<underseas> -> (undersea valleys | undersea mountains)

;; Regla de reescritura para reconocer en una solo pregunta diferentes
;; formas de referirse a los distintos tipos de features.
;;
;;
((!init-of-sentence:=(* $))
 (!feature-type:=((&i feature features) | 
 		(&i administrative <administratives>) | 
		(&i hydrographic <hydrographics>) |
		(&i area <areas>) |
		(&i place <places>) |
		(&i road <roads>) |
		(&i spot <spots>) |
		(&i hypsographic <hypsographics>) |
		(&i udrsea <underseas>) |
		(&i vegetation <vegetation>) )
 ) (!end-of-sentence:=(* $)) 
) 
::>
(append !init-of-sentence !feature-type !end-of-sentence)

4	Funciones Lisp
4.1	Librerías utilizadas
En el desarrollo de este trabajo, se han utilizado dos librerías de libre distribución (http://opensource.franz.com/): 
•	AllegroServe: que permite realizar conexiones http y ofrece, además un HTTP/1.1 compliant web server.
•	Xmlutils: que ofrece un parser de HTML/XML, y que básicamente permite convertir ambos a una estructura de lista.
4.2	Parsear GML
Para el parseo de GML se ha utilizado una librería que permite dada una cadena, convertirlo a una estructura de lista y se han implementado ciertas funciones que han permito pasear el GML para este dominio concreto de aplicación. Se ha estudiado la estructura concreta de la lista que contiene el GML que devuelve este WFS específico, y en base a eso se han extraído las propiedades que resultaban relevantes, para almacenarlas en los frames correspondientes. El principal inconveniente encontrado ha sido que no se ha podido eliminar de la cadena, un carácter que representa una especie de salto línea, y por lo tanto esto debía ser tenido en cuenta como elemento en la estructura de lista obtenida tras el parseo. 
5	Futuras mejoras
Como futuras mejoras se plantean por un lado aquellas relacionadas con dotar de mayor poder expresivo al lenguaje que debe interpretarse, y por otro al empleo de técnicas más genéricas y completas de parseo de GML. En el caso de servidores de features de líneas o de polígonos, podrían diseñarse un amplio abanico de preguntas espaciales. Además, también pueden incluirse peticiones en las que se vean involucrados varios servidores de features, por ejemplo, dame los coches que se encuentran a 5 metros de Zaragoza, o dame las parcelas en un radio de 3 kilómetros de un lugar. En lo referente al parseo del GML, existen  algunas librerías que ofrecen una serie de funciones que permiten parsear XML de forma general pudiendo recuperar tags específicos,  atributos, etc...
6	Principales dificultades
Los principales problemas encontrados han sido debidos al hecho de tener que transformar las cadenas a símbolos y al contrario. En el caso de transformación de cadenas a símbolos, lo más complicado ha sido la traducción de una cadena que representa las coordenadas geográficas del punto(float) a un símbolo que represente un número, ya que sólo disponía de una función que parsea una cadena a un entero. La solución ha sido parsear por un lado la parte entera, y por otro la parte decimal, y una vez reconocidas recomponer la coordenada. En el caso contrario, el problema es que al intentar introducir en el slot de un frame el nombre geográfico, la cadena que se obtiene del GML, debe transformarse a un símbolo, y en el caso de que el nombre contenga más de una palabra el símbolo que se obtiene es de este estilo |Estación de Parchite|, lo que debe ser tenido en cuenta  a la hora de buscar el frame que el usuario haya solicitado, haciendo las transformaciones oportunas (de lista de símbolos a cadena y de cadena a símbolos).   

A la hora de realizar preguntas referentes a la distancia a la que se encuentra un objeto de otro, ha sido imposible especificarlo en el filtro mediante la utilización de los operadores Within y Beyond. La solución propuesta es utilizar una operación de BBOX, en la que se especifica si un objeto está dentro de otro, por lo que se especifica un bounding box alrededor del punto en base a la distancia requerida. El principal inconveniente de esta solución, es que las distancias sólo pueden ser expresadas en grados.

A1 Especificación de la gramática
;*********************************************************************
; Módulo: WFS
; Uso:    Interface de lenguaje natural para interrogar un Web Feature 
;	  Server. Fichero de gramática.
; Autor:  María Navas Tapiador
; email:  mnavas@ebro.cps.unizar.es
;*********************************************************************
; Fichero: wfs.gra      Fecha Creación: 19 de Junio de 2002
; Versión: 1.0          Fecha Modificación:30de Junio del 2002 
; Estado:  Desarrollo   Autor: María Navas Tapiador
;---------------------------------------------------------------------
;*********************************************************************

<be-present> -> (is | are | be | am)

<what-q> -> (<www> <be-present> | <www> <poss>)
<www> -> (which | what)
<poss> -> (%apost s)

<with> -> (with)

<feature> -> (feature| features)

<contain> -> (contain | contains)
<search-verb> -> (end with| ends with| begin with| begins with)

<me-us> -> (me | us)
<pos-modal> -> (could | would | can )
<polite> -> (<pos-modal> you)

<info-req1> -> (?<polite> <info-req2> ?<what-q>)
<info-req2> -> (tell <me-us> | give <me-us> | print | type)

<info-req> -> (<what-q> | <info-req1>)

<the> -> (the)
<that> -> (that)
<of> -> (of|in)
<from> -> (from)

<known> -> (you <know-have> | ?is known)
<know-have> -> (know | have)
<prp-about> -> (about | of) 
<all> -> (all)

<punct> -> (%qmark | <dpunct>)
<dpunct> -> (%period | %emark)

<typeof> -> (<type> (&o of) (&o a))
<typeSingular> -> (type | kind | form | instance | example | subclass)
<typePlural> -> (types | kinds | forms | instances | examples | subclasses)
<type> -> (<typeSingular> | <typePlural>)
<a-an> -> (a | an)
<not> -> (not | no)

<near> -> (near)
<far> -> (far) 
<distance> -> (<near> | <far>)

<distance-expr> -> (<near> | <far> <from>)

<administratives> -> (administrative divisions | political entities)
<hydrographics> -> (bays | lakes | seas | rivers | oceans |ponds)
<areas> -> (areas | coasts | republics | regions | reserves)
<places> -> (places | villages | cities )
<roads> -> (roads | railroads | tunels)
<spots> -> (interesting places | stations | spots)
<hypsographics> -> (beachs | cliffs | deltas |depressions | dessert)
<underseas> -> (undersea valleys | undersea mountains)
<vegetation> -> (forests | vineyards | vegetations)

<feature-type> -> (feature | administrative | hydrographic | area | place |road | spot | hypsographic | udrsea | vegetation)

<degrees> -> (degree | degrees)
<minutes> -> (minute | minutes)

;; Reescritura de una regla para pasar de minutos a grados.
;;
;;
((!init-of-sentence:=(* $)) (!valor:=$n) <minutes> 
  (!s2:=$r) 
) 
::>
(append !init-of-sentence (list (/ (first !valor) 60.0)) '(degrees) !s2)

;; Regla de reescritura para reconocer en una solo pregunta diferentes
;; formas de referirse a los distintos tipos de features.
;;
;;
((!init-of-sentence:=(* $))
 (!feature-type:=((&i feature features) | 
 		(&i administrative <administratives>) | 
		(&i hydrographic <hydrographics>) |
		(&i area <areas>) |
		(&i place <places>) |
		(&i road <roads>) |
		(&i spot <spots>) |
		(&i hypsographic <hypsographics>) |
		(&i udrsea <underseas>) |
		(&i vegetation <vegetation>) )
 ) (!end-of-sentence:=(* $)) 
) 
::>
(append !init-of-sentence !feature-type !end-of-sentence)

;;
;; 1.-
;;
;; Preguntas acerca de los diferentes features/tipos de features concretos que se obtienen a 
;; parir de ciertas carcterísticas de la cadena que los representa.
;;
;; E.g.: Which feature/s end/s with libol? 
;;       Which road/s begin with Carr?
;;       Which place/s contains chite?
;;     
;;
(<www> (!type:=<feature-type>) (!verb:=(<search-verb>|<contain>)) (!class:=(+ $w)) (&o %qmark))
=>

(if (equal (first !type) 'feature)
	(print-features-contains !class (first !verb))
	(print-types-contains (first !type) !class (first !verb))
)

;;
;; 2.-
;;
;; Preguntas acerca de los diferentes features/tipos de features que se encuentran cerca o lejos
;;
;; E.g.: Which feature/s are near Zaragoza?
;;       Which places are far from Huesca? 
;;     
;;
(<www> (!type-f:=<feature-type>) <be-present> (!type:=<distance-expr>) (!class:=(+ $w)) (&o %qmark))
=>
(if (equal (first !type-f) 'feature)
	(print-features-distance  (first !type) !class)
	(print-types-distance (first !type) (first !type-f) !class))

;;
;; 2b.-
;;
;; Preguntas acerca de los diferentes features/tipos de features que se encuentran a cierta distancia
;; de otro
;;
;; E.g.: Which feature/s are 5 degrees from Zaragoza?
;;       Which roads are 3 degrees from Huesca?
;;     
;;
(<www> (!type-f:=<feature-type>) <be-present> (!distance:=$n) <degrees> <from> (!class:=(+ $w)) (&o %qmark))
=>
(if (equal (first !type-f) 'feature)
	(register-print-features-distance  (first !distance) !class)
	(register-print-types-distance (first !distance) (first !type-f) !class)
)

;;
;; 3.-
;;
;; Preguntas acerca de los diferentes features/tipos de features de un determinado país
;;
;; E.g.: Could you give me the roads in Spain?
;;     
;;
(<info-req1> <the> (!feature:=<feature-type>) <of> (!class:=$w) (&o %qmark))
=>
(if (equal (first !feature) 'feature)
	(print-features-country (first !class))
	(print-types-country (first !feature) (first !class))
)

;; 4.-
;;
;; Registrar distancias, evitando la escritura de una determinada
;;
;; E.g.: Near is five degrees
;;       Far is 20 degrees
;;
;;
((!type:=(&o <distance>)) <be-present> (!degrees:= $n) <degrees>) 
=>
   (set-distance  (first !type) (first !degrees))

;; 5.-
;;
;; Obtener información sobre un feature concreto a partir del nombre
;;
;; E.g: Tell me that you know about Pirineos.
;; 
;;
;;
(<info-req2> ?<all> ?<that> ?<known> <prp-about> (!class:=(+ $w)))
=>
   (describe-feature !class)

;; 6.-
;;
;; Salir de Dypar
;;
;;
;;
<exit> -> (quit | exit | end ?$ session | ?good bye)
(<exit> $r) => 'exit
A2  Funciones LISP 
;*********************************************************************
; Módulo: WFS
; Uso:    Interface de lenguaje natural para interrogar un Web Feature 
;	  Server. Fichero que contiene las funciones lisp utilizadas 
;         por el parser
; Autor:  María Navas Tapiador
; email:  mnavas@ebro.cps.unizar.es
;*********************************************************************
; Fichero: wfs.lsp      Fecha Creación: 19 de Junio de 2002
; Versión: 1.0          Fecha Modificación: 
; Estado:  Desarrollo   Autor: María Navas Tapiador
;---------------------------------------------------------------------
;*********************************************************************

; **********************************
; * Funciones de manejo de cadenas *
; **********************************
;;
;; Recibe como argumento una lista de elementos y devuelve una
;; cadena en mayúsculas con los elementos de la lista concatenados.
;;
;; E.g.: (list-to-single-word '(police car)) -> "policeCar"
;;
(defun list-to-single-word (list)
   (let ((stringfied-list "")
         (string-to-append ""))
     (dolist (element list stringfied-list)
          (setq string-to-append (to-upcase-string element))
           (if (not (equal stringfied-list ""))
           	(setq stringfied-list
           	   (concatenate 'string stringfied-list " ")))
              
           (setq stringfied-list
              (concatenate 'string stringfied-list string-to-append)))))

;;
;; Recibe como argumento un atom y lo devuelve en minúsculas
;;
;; E.g.: (to-downcase-string 'PoLice) -> "police"
;;
(defun to-downcase-string (atom)
   (string-downcase (atom-to-string atom)))

;;
;; Recibe como argumento un atom y lo devuelve en mayúsculas
;;
;; E.g.: (to-upcase-string 'PoLice) -> "POLICE"
;;
(defun to-upcase-string (atom)
   (string-upcase (atom-to-string atom)))

;;
;; Recibe como argumento un atom y lo devuelve con la primera
;; letra en mayúsculas y el resto en minúsculas.
;;
;; E.g.: (to-capitalized-string 'police) -> "Police"
;;
(defun to-capitalized-string (atom)
   (string-capitalize (atom-to-string atom)))

;;
;; Recibe como argumento un atom y lo devuelve en una cadena
;; sin preocuparse de mayúsculas y minúsculas
;;
;; E.g.: (atom-to-string 'police) -> "POLICE"
;;
(defun atom-to-string (atom)
   (format nil "~a" atom))

;;
;; Obtiene el símbolo correspondiente a una cadena.
;;
(defun string-to-symbol (string)
   (intern (to-upcase-string string)))

;;
;; Comprueba si una cadena contiene algunas de las subcadenas 
;; especificadas en una lista.
;;
(defun is-substring-list (list startIndex word)
   (let ((result nil))
      (dolist (word-list list result)
         (if (string= (subseq (string-downcase word) 
                      (- (length word) (length word-list))) 
                  (string-downcase word-list)
             )
            (setq result word-list) ))))

; *******************************************************
; * Funciones de acceso al Web features Server del NIMA *
; *******************************************************

;;
;; Función que concatena dos filtros.
;;
;;
(defun filter-and (filter1 filter2)
  (concatenate 'string (concatenate 'string "<Filter><And>" (concatenate 'string filter1 filter2)) "</And></Filter>"))

;;
;; Función que realiza una pregunta a partir de un filtro 
;; y registra sus resultados en frames.
;;
;;
(defun register-gml (f)
  (setq filter (append '("FILTER") f))

  (setq query (list '("REQUEST" . "GETFEATURE")  '("TYPENAME" . "gns") filter '("OUTPUTFORMAT" . "GML2") '("MAXFEATURES" . 20) '("INITIALFEATURE" . 1)))
  
  (setq qur (net.aserve.client:do-http-request "http://artieda.cps.unizar.es/wfsGazetteerGns/servlets/GNS?VERSION=0.0.14" :query query)) 
  
  (parser-gml qur) )

;;
;; Función que parsea el GML obtenido en una petición al Web Features Server, 
;; transformándolo en una lista, extrayendo cada uno de los features,
;; encontrados y almacenándolos como frames.
;;
;;
(defun parser-gml (query)

(setq query (net.xml.parser:parse-xml (remove  #\return query)))

;; quito el XML
;; quito el featureCollection
;; quito el BoundedBy
(setq info (rest (rest (first (rest query))))) 

(if (not (equal info nil)) 
  (progn 	
	(setq features-list (rest (rest info)))
	(setq l (list-length features-list))

	(let ((result nil))
	   (dotimes (count l result)
	       (if (eq (mod count 2) 0)
	       	 (register-feature (first (nthcdr count features-list)))))))))

;;
;;
;; Función que a partir del GML parseado en forma de lista de cada feature, 
;; obtiene sus propiedades y las almacena en un frame sino lo está.
;;
;;
(defun register-feature (list)

;FeatureMember 
(setq feature (first (rest (rest list))))

;propiedad nombre
(setq name (second (first (nthcdr 4 feature))))

(if (equal (is-a? 'objeto (string-to-symbol name)) nil)
	(save-feature feature name))

(pprint name)
(pprint "Descripcion:")
(pprint (describe-form  (string-to-symbol name))))

;;
;; Función que guarda las propiedades del feature en un frame.
;;
;;
(defun save-feature (feature name)
;propiedad clase Feature más general

(setq generic (second (first (nthcdr 14 feature))))
(set-value (string-to-symbol name)  'fc (string-to-symbol generic)) 

(setq type 'feature)
(case (string-to-symbol generic) ('A (setq type 'Administrative))
				 ('H (setq type 'Hydrographic))
				 ('L (setq type 'Area))
				 ('P (setq type 'Place))
				 ('R (setq type 'Road))
				 ('S (setq type 'Spot))
				 ('T (setq type 'Hypsographic))
				 ('U (setq type 'Undersea))
				 ('V (setq type 'Vegetation)))

(form :name (string-to-symbol name) :is-a type)

(setq location (second (first (nthcdr 2 (first (nthcdr 2 (first (nthcdr 6 feature))))))))

(setq result1 (multiple-value-bind (prefixlat point) 
     (parse-integer (string location) :junk-allowed t) (list prefixlat point))) 

(setq result2 (multiple-value-bind (suffixlat comma) 
     (parse-integer (string location) :start (+ (second result1) 1) :junk-allowed t) (list suffixlat comma))) 

(setq result3 (multiple-value-bind (preffixlong point) 
     (parse-integer (string location) :start (+ (second result2) 1) :junk-allowed t) (list preffixlong point))) 

(setq result4 (multiple-value-bind (suffixlong comma) 
     (parse-integer (string location) :start (+ (second result3) 1) :junk-allowed t) (list suffixlong comma))) 

(setq lat (+ (first result1) (* (first result2) (expt 10 (* -1.0 (length (atom-to-string (first result2))))))))
(setq long (+ (first result3) (* (first result4) (expt 10 (* -1.0 (length (atom-to-string (first result4)))))) ))

(if (equal (char (string location) 0)#\-)
	(setq lat (* -1.0 lat)))

(set-value (string-to-symbol name)  'latitud lat)
(set-value (string-to-symbol name)  'longitud long)

;propiedad clase  feature más específica
(setq especialized (second (first (nthcdr 8 feature))))
(set-value (string-to-symbol name)  'featureDesignation (string-to-symbol especialized))

;propiedad pais Feature
(setq country (second (first (nthcdr 16 feature))))
(set-value (string-to-symbol name)  'country (string-to-symbol country))

;propiedad tipo de nombre Feature
(setq name-type (second (first (nthcdr 20 feature))))
(set-value (string-to-symbol name)  'nameType (string-to-symbol name-type)))

;;
;; Receives as an argument an element and a verb
;; and return the corresponding features that end/begin/contains 
;; (indicated by the verb) the element, querying the Web feature server
;;
;;
(defun print-features-contains (element verb)
       
  (if (is-substring-list '("end" "ends") 0 (atom-to-string verb))
	(setq filter1 
		(format nil "<Filter><PropertyIsLike><PropertyName>name</PropertyName><Literal>%~a</Literal></PropertyIsLike></Filter>" (list-to-single-word element))) 

	(if (is-substring-list '("contain" "contains") 0 (atom-to-string verb))
	    (setq filter1
		(format nil "<PropertyIsLike><PropertyName>name</PropertyName><Literal>%~a%</Literal></PropertyIsLike>" (list-to-single-word element))) 
	    (setq filter1 
		(format nil "<PropertyIsLike><PropertyName>name</PropertyName><Literal>~a%</Literal></PropertyIsLike>" (list-to-single-word element))))) 
	
  (register-gml filter1))

;;
;; Receives as an argument a feature type, an element and a verb
;; and return the corresponding features that end/begin/contains 
;; (indicated by the verb) the element, querying the Web feature server
;;
;;
(defun print-types-contains (type element verb)
  
  (if (is-substring-list '("end" "ends") 0 (atom-to-string verb))
	(setq filter1 
		(format nil "<PropertyIsLike><PropertyName>name</PropertyName><Literal>%~a</Literal></PropertyIsLike>" (list-to-single-word element))) 

	(if (is-substring-list '("contain" "contains") 0 (atom-to-string verb))
	    (setq filter1
		(format nil "<PropertyIsLike><PropertyName>name</PropertyName><Literal>%~a%</Literal></PropertyIsLike>" (list-to-single-word element))) 
	    (setq filter1 
		(format nil "<PropertyIsLike><PropertyName>name</PropertyName><Literal>~a%</Literal></PropertyIsLike>" (list-to-single-word element))))) 

  (setq filter2 (format nil "<PropertyIsEqualTo><PropertyName>fc</PropertyName><Literal>~a</Literal></PropertyIsEqualTo>" (get-value type 'fc)))			  

  (setq filtro (filter-and filter1 filter2))
  (register-gml filtro))

;;
;; Crea el filtro que permite preguntar por los elemntos que se encuentran como mucho a
;; la distancia especificada en near de la latitud y longitud que se pasa como parámetro.
;;
(defun filter-near (latitud longitud type)
  (setq degrees (get-value type 'degrees))

  (format nil "<BBOX><PropertyName>location</PropertyName><Polygon srsName='EPSG:4326'><outerBoundaryIs>
                        <LinearRing>
                              <coordinates>~a,~a ~a,~a ~a,~a ~a,~a ~a,~a</coordinates>
                        </LinearRing>
                  </outerBoundaryIs>
            </Polygon>
            </BBOX>" (- latitud degrees) (+ longitud degrees) (+ latitud degrees) (+ longitud degrees) (- latitud degrees) (- longitud degrees) (+ latitud degrees) (- longitud degrees) (- latitud degrees) (+ longitud degrees)))

;;
;; Crea el filtro que permite preguntar por los elemntos que se encuentran como mínimo a
;; la distancia especificada en near de la latitud y longitud que se pasa como parámetro.
;;
(defun filter-far (latitud longitud)
  (setq degrees (get-value 'far 'degrees))

  (format nil "<Not><BBOX><PropertyName>location</PropertyName><Polygon srsName='EPSG:4326'><outerBoundaryIs>
                        <LinearRing>
                              <coordinates>~a,~a ~a,~a ~a,~a ~a,~a ~a,~a</coordinates>
                        </LinearRing>
                  </outerBoundaryIs>
            </Polygon>
            </BBOX></Not>" (- latitud degrees) (+ longitud degrees) (+ latitud degrees) (+ longitud degrees) (- latitud degrees) (- longitud degrees) (+ latitud degrees) (- longitud degrees) (- latitud degrees) (+ longitud degrees)) )

;;
;; Recibe como argumento un elemento y devuelve las features que están a
;; una cierta distancia (near o far) de ese elemento.
;;
(defun print-features-distance (type element)

 (setq filter (format nil "<Filter><PropertyIsLike><PropertyName>name</PropertyName><Literal>~a</Literal></PropertyIsLike></Filter>" (list-to-single-word element)))
 
 (if (equal (is-a? (string-to-symbol (list-to-single-word element)) 'objeto) nil)
  	(register-gml filter)
   	(progn (pprint (list-to-single-word element))
  	       (pprint "Descripcion:")
  	       (pprint (describe-form  (string-to-symbol (list-to-single-word element)))))  )
	
 (if (not (equal (is-a? (string-to-symbol (list-to-single-word element)) 'objeto) nil))
   (progn 
 	(setq latitud (get-value (string-to-symbol (list-to-single-word element)) 'latitud))
 	(setq longitud (get-value (string-to-symbol (list-to-single-word element)) 'longitud))
	 (if (not (equal type 'far))
	 	(setq fdistance  (filter-near latitud longitud type))
	 	(setq fdistance  (filter-far latitud longitud)))
 
	 (register-gml (concatenate 'string "<Filter>" (concatenate 'string fdistance "</Filter>"))))))

;;
;; Recibe como argumento un elemento y devuelve los tipos de features especificados como parámetro
;; que están a una cierta distancia (near o far) de ese elemento.
;;
(defun print-types-distance (type feature element)

 (setq filter (format nil "<Filter><PropertyIsLike><PropertyName>name</PropertyName><Literal>~a</Literal></PropertyIsLike></Filter>" (list-to-single-word element)))
 
 (if (equal (is-a? (string-to-symbol (list-to-single-word element)) 'objeto) nil)
  	(register-gml filter)
   	(progn (pprint (list-to-single-word element))
  	       (pprint "Descripcion:")
  	       (pprint (describe-form  (string-to-symbol (list-to-single-word element))))))

 (if (not (equal (is-a? (string-to-symbol (list-to-single-word element)) 'objeto) nil))
   (progn 
	 (setq latitud (get-value (string-to-symbol (list-to-single-word element)) 'latitud))
	 (setq longitud (get-value (string-to-symbol (list-to-single-word element)) 'longitud)) 
	 (if (not (equal type 'far))
	 	(setq fdistance  (filter-near latitud longitud type))
	 	(setq fdistance  (filter-far latitud longitud))
	 )

	 (setq filter2 (format nil "<PropertyIsEqualTo><PropertyName>fc</PropertyName><Literal>~a</Literal></PropertyIsEqualTo>" (get-value feature 'fc)))			  

	 (setq f (filter-and fdistance filter2))
	 (register-gml f))))

;;
;; Permite obtener los elementos que se encuentran a una distancia en grados 
;; dist del elemento element 
;;
(defun register-print-features-distance (dist element)
 (set-distance 'distance-max dist) 
 (print-features-distance 'distance-max element))

;;
;; Permite obtener los features de un tipo que se encuentran a una distancia en grados 
;; dist del elemento element 
;;
(defun register-print-types-distance (dist type element)
 (set-distance 'distance-max dist) 
 (print-types-distance 'distance-max type element))

;;
;; Permite obtener los features de un determinado país que se le pasa como parámetro
;;
(defun print-features-country (country)

(if (equal (get-value  country 'siglas) nil)
	(setq count " ")
	(setq count (get-value  country 'siglas)))

(setq filter
	(format nil "<Filter>
			  <PropertyIsEqualTo>
			  	<PropertyName>country</PropertyName><Literal>~a</Literal>
			  </PropertyIsEqualTo>
		      </Filter>" count)) 
	
  (register-gml filter))

;;
;; Permite obtener los features de un tipo de un determinado país que se le pasa como parámetro
;;
(defun print-types-country (element country)

(if (equal (get-value  country 'siglas) nil)
	(setq count " ")
	(setq count (get-value  country 'siglas))
)
(setq filter1
	(format nil "<PropertyIsEqualTo>
			  	<PropertyName>country</PropertyName><Literal>~a</Literal>
			  </PropertyIsEqualTo>
		     " count)) 
(setq filter2
	(format nil "<PropertyIsEqualTo>
			  	<PropertyName>fc</PropertyName><Literal>~a</Literal>
			  </PropertyIsEqualTo>" (get-value element 'fc))) 
	
(setq filter (filter-and filter1 filter2))	
(register-gml filter))

;;
;; Permite especificar un valor para los tipos de distancia (near-far)
;;
(defun set-distance (type quantity)
   (form :name type :is-a 'distance)
   (set-value type 'degrees quantity))

;;
;; Muestra la descripción del feature element que se le pasa como parámetro
;;
(defun describe-feature (element)
 (setq filter (format nil "<Filter><PropertyIsLike><PropertyName>name</PropertyName><Literal>~a</Literal></PropertyIsLike></Filter>" (list-to-single-word element)))
  (if (equal (is-a? (string-to-symbol (list-to-single-word element)) 'objeto) nil)
	(register-gml filter)
 	(progn (pprint (list-to-single-word element))
	       (pprint "Descripcion:")
	       (pprint (describe-form  (string-to-symbol (list-to-single-word element))))))))

; **********************
; * Inicia la gramática*
; **********************
;;
;; Inicializa la grámatica cuyo nombre se le pasa como parámetro,
;; (la extensión .gra es opcional) y en caso de que no se le
;; pase ninguna utiliza por defecto la de wfs
;;
(defun initgra (&optional (nombreGra "wfs"))
   (erasegra)
   (loadgra nombreGra))
A3 Ejemplos

Se presentan unos cuántos ejemplos de interacción para cada uno de los tipos de preguntas. En estos ejemplos de interacción se ha limitado el número máximo de features a devolver a 5.

Preguntas a través del nombre.

+ Which features begin with Jar?

"Jar Iflis"
"Descripcion:"
|JAR IFLIS| is a(n) HYPSOGRAPHIC 
Atributos 
 LATITUD: 2.7166667 
 LONGITUD: 34.883335 
 FEATUREDESIGNATION: HLL 
 COUNTRY: MO 
 NAMETYPE: N 
 FC: T 
Tiene 

NIL
"Jar Irhzra"
"Descripcion:"
|JAR IRHZRA| is a(n) HYPSOGRAPHIC 
Atributos 
 LATITUD: 2.5833333 
 LONGITUD: 34.533333 
 FEATUREDESIGNATION: MT 
 COUNTRY: MO 
 NAMETYPE: N 
 FC: T 
Tiene 

NIL
"Jar Izra"
"Descripcion:"
|JAR IZRA| is a(n) HYPSOGRAPHIC 
Atributos 
 LATITUD: 2.5833333 
 LONGITUD: 34.533333 
 FEATUREDESIGNATION: MT 
 COUNTRY: MO 
 NAMETYPE: V 
 FC: T 
Tiene 

NIL
"Jaraba"
"Descripcion:"
JARABA is a(n) PLACE 
Atributos 
 LATITUD: 0.116666675 
 LONGITUD: 41.183334 
 FEATUREDESIGNATION: PPL 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: P 
Tiene 

NIL
"Jaraco"
"Descripcion:"
JARACO is a(n) PLACE 
Atributos 
 LATITUD: -0.2166667 
 LONGITUD: 39.333332 
 FEATUREDESIGNATION: PPL 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: P 
Tiene 

NIL

+ Which places ends with chite?

"Nechite"
"Descripcion:"
NECHITE is a(n) PLACE 
Atributos 
 LATITUD: 2.333333 
 LONGITUD: 37.0 
 FEATUREDESIGNATION: PPL 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: P 
Tiene 

NIL
"Chite"
"Descripcion:"
CHITE is a(n) PLACE 
Atributos 
 LATITUD: 2.45 
 LONGITUD: 36.933334 
 FEATUREDESIGNATION: PPL 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: P 
Tiene 

NIL
"Belchite"
"Descripcion:"
BELCHITE is a(n) PLACE 
Atributos 
 LATITUD: -0.75 
 LONGITUD: 41.3 
 FEATUREDESIGNATION: PPL 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: P 
Tiene 

NIL
"Zbor el Mchite"
"Descripcion:"
|ZBOR EL MCHITE| is a(n) PLACE 
Atributos 
 LATITUD: 3.0666666 
 LONGITUD: 34.566666 
 FEATUREDESIGNATION: PPL 
 COUNTRY: MO 
 NAMETYPE: V 
 FC: P 
Tiene 

NIL
"Monchite"
"Descripcion:"
MONCHITE is a(n) PLACE 
Atributos 
 LATITUD: 7.5 
 LONGITUD: 39.683334 
 FEATUREDESIGNATION: PPL 
 COUNTRY: PO 
 NAMETYPE: N 
 FC: P 
Tiene 

NIL

+ Which rivers contains ebro?

"Canal de la Izquierda del Ebro"
"Descripcion:"
|CANAL DE LA IZQUIERDA DEL EBRO| is a(n) HYDROGRAPHIC 
Atributos 
 LATITUD: 0.5 
 LONGITUD: 40.933334 
 FEATUREDESIGNATION: CNLI 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: H 
Tiene 

NIL
"Hoya de los Enebros"
"Descripcion:"
|HOYA DE LOS ENEBROS| is a(n) HYDROGRAPHIC 
Atributos 
 LATITUD: 0.050000012 
 LONGITUD: 40.166668 
 FEATUREDESIGNATION: PNDI 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: H 
Tiene 

NIL
"Río Ebrón"
"Descripcion:"
|RÍO EBRÓN| is a(n) HYDROGRAPHIC 
Atributos 
 LATITUD: 0.75 
 LONGITUD: 40.1 
 FEATUREDESIGNATION: STM 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: H 
Tiene 

NIL
"Canal del Ebro de la Derecha"
"Descripcion:"
|CANAL DEL EBRO DE LA DERECHA| is a(n) HYDROGRAPHIC 
Atributos 
 LATITUD: 0.3333333 
 LONGITUD: 40.916668 
 FEATUREDESIGNATION: CNLI 
 COUNTRY: SP 
 NAMETYPE: V 
 FC: H 
Tiene 

NIL

"Río Ebro"
"Descripcion:"
|RÍO EBRO| is a(n) HYDROGRAPHIC 
Atributos 
 LATITUD: 0.90000004 
 LONGITUD: 40.716667 
 FEATUREDESIGNATION: STM 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: H 
Tiene 

NIL

Preguntar por las propiedades de un elemento.

+ Tell me all about Huesca

"Huesca"
"Descripcion:"
HUESCA is a(n) PLACE 
Atributos 
 LATITUD: -0.41666672 
 LONGITUD: 42.133335 
 FEATUREDESIGNATION: PPL 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: P 
Tiene 

NIL

+ Print about Pirineos

"Pirineos"
"Descripcion:"
PIRINEOS is a(n) HYPSOGRAPHIC 
Atributos 
 LATITUD: 1.0 
 LONGITUD: 42.666668 
 FEATUREDESIGNATION: MTS 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: T 
Tiene 

NIL

Preguntas por país.

+ Could you give me the spots in France?

"Château de Courcelles"
"Descripcion:"
|CHÂTEAU DE COURCELLES| is a(n) SPOT 
Atributos 
 LATITUD: 6.15 
 LONGITUD: 47.766666 
 FEATUREDESIGNATION: HSEC 
 COUNTRY: FR 
 NAMETYPE: N 
 FC: S 
Tiene 

NIL
"Château des 4 Tours"
"Descripcion:"
|CHÂTEAU DES 4 TOURS| is a(n) SPOT 
Atributos 
 LATITUD: 5.25 
 LONGITUD: 43.533333 
 FEATUREDESIGNATION: HSEC 
 COUNTRY: FR 
 NAMETYPE: V 
 FC: S 
Tiene 

NIL
"Fort des 4 Seigneurs"
"Descripcion:"
|FORT DES 4 SEIGNEURS| is a(n) SPOT 
Atributos 
 LATITUD: 5.8 
 LONGITUD: 45.15 
 FEATUREDESIGNATION: FT 
 COUNTRY: FR 
 NAMETYPE: V 
 FC: S 
Tiene 

NIL
"Château d' Yssertieux"
"Descripcion:"
|CHÂTEAU D' YSSERTIEUX| is a(n) SPOT 
Atributos 
 LATITUD: 2.7166667 
 LONGITUD: 46.85 
 FEATUREDESIGNATION: HSEC 
 COUNTRY: FR 
 NAMETYPE: N 
 FC: S 
Tiene 

NIL
"Yonval"
"Descripcion:"
YONVAL is a(n) SPOT 
Atributos 
 LATITUD: 4.866667 
 LONGITUD: 48.9 
 FEATUREDESIGNATION: FRM 
 COUNTRY: FR 
 NAMETYPE: N 
 FC: S 
Tiene 

NIL

+ Could you give me the administrative divisions in Spain?

"Provincia de Zaragoza"
"Descripcion:"
|PROVINCIA DE ZARAGOZA| is a(n) ADMINISTRATIVE 
Atributos 
 LATITUD: 1.0 
 LONGITUD: 41.583332 
 FEATUREDESIGNATION: ADMD 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: A 
Tiene 

NIL
"Provincia de Zamora"
"Descripcion:"
|PROVINCIA DE ZAMORA| is a(n) ADMINISTRATIVE 
Atributos 
 LATITUD: 6.0 
 LONGITUD: 41.75 
 FEATUREDESIGNATION: ADMD 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: A 
Tiene 

NIL
"Zalla"
"Descripcion:"
ZALLA is a(n) ADMINISTRATIVE 
Atributos 
 LATITUD: 2.8666668 
 LONGITUD: 43.216667 
 FEATUREDESIGNATION: ADMD 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: A 
Tiene 

NIL
"Provincia de Vizcaya"
"Descripcion:"
|PROVINCIA DE VIZCAYA| is a(n) ADMINISTRATIVE 
Atributos 
 LATITUD: 1.0833333 
 LONGITUD: 43.25 
 FEATUREDESIGNATION: ADMD 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: A 
Tiene 

NIL
"Villa de Cruces"
"Descripcion:"
|VILLA DE CRUCES| is a(n) ADMINISTRATIVE 
Atributos 
 LATITUD: 7.7833333 
 LONGITUD: 42.8 
 FEATUREDESIGNATION: ADM2 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: A 
Tiene 

NIL

+ Could you give me the features in Vatican?

+ Could you give me the features in Andorra?

+ Could you give me the features in Gibraltar?

"Rosia Parade"
"Descripcion:"
|ROSIA PARADE| is a(n) SPOT 
Atributos 
 LATITUD: 4.65 
 LONGITUD: 36.116665 
 FEATUREDESIGNATION: SQR 
 COUNTRY: GI 
 NAMETYPE: N 
 FC: S 
Tiene 

NIL
"Withams Cemetery"
"Descripcion:"
|WITHAMS CEMETERY| is a(n) SPOT 
Atributos 
 LATITUD: 4.6666665 
 LONGITUD: 36.116665 
 FEATUREDESIGNATION: CMTY 
 COUNTRY: GI 
 NAMETYPE: N 
 FC: S 
Tiene 

NIL
"Windmill Hill Flats"
"Descripcion:"
|WINDMILL HILL FLATS| is a(n) HYPSOGRAPHIC 
Atributos 
 LATITUD: 4.6666665 
 LONGITUD: 36.1 
 FEATUREDESIGNATION: TRR 
 COUNTRY: GI 
 NAMETYPE: N 
 FC: T 
Tiene 

NIL
"Williams Way Tunnel"
"Descripcion:"
|WILLIAMS WAY TUNNEL| is a(n) ROAD 
Atributos 
 LATITUD: 4.6666665 
 LONGITUD: 36.133335 
 FEATUREDESIGNATION: TNLRD 
 COUNTRY: GI 
 NAMETYPE: N 
 FC: R 
Tiene 

NIL
"White Rock"
"Descripcion:"
|WHITE ROCK| is a(n) HYPSOGRAPHIC 
Atributos 
 LATITUD: 4.6666665 
 LONGITUD: 36.133335 
 FEATUREDESIGNATION: RK 
 COUNTRY: GI 
 NAMETYPE: N 
 FC: T 
Tiene 

NIL

Preguntas por los elementos a cierta distancia de uno dado.

+ near is 8 minutes

+ Which features are near Huesca?

"HUESCA"
"Descripcion:"

HUESCA is a(n) PLACE 
Atributos 
 LATITUD: -0.41666672 
 LONGITUD: 42.133335 
 FEATUREDESIGNATION: PPL 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: P 
Tiene 

NIL

"Tabernas de Isuela"
"Descripcion:"
|TABERNAS DE ISUELA| is a(n) PLACE 
Atributos 
 LATITUD: -0.41666672 
 LONGITUD: 42.5 
 FEATUREDESIGNATION: PPL 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: P 
Tiene 

NIL
"Barranco de Valdabra"
"Descripcion:"
|BARRANCO DE VALDABRA| is a(n) HYDROGRAPHIC 
Atributos 
 LATITUD: -0.41666672 
 LONGITUD: 42.333332 
 FEATUREDESIGNATION: STM 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: H 
Tiene 

NIL
"Buñales"
"Descripcion:"
BUÑALES is a(n) PLACE 
Atributos 
 LATITUD: -0.4 
 LONGITUD: 42.5 
 FEATUREDESIGNATION: PPL 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: P 
Tiene 

NIL
"Río Isuela"
"Descripcion:"
|RÍO ISUELA| is a(n) HYDROGRAPHIC 
Atributos 
 LATITUD: -0.4 
 LONGITUD: 42.5 
 FEATUREDESIGNATION: STM 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: H 
Tiene 

NIL

+ far is 20 degrees

+ Which areas are far from Zaragoza?

"Zaragoza"
"Descripcion:"
ZARAGOZA is a(n) PLACE 
Atributos 
 LATITUD: -0.8833333 
 LONGITUD: 41.633335 
 FEATUREDESIGNATION: PPL 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: P 
Tiene 

NIL

"Achada"
"Descripcion:"
ACHADA is a(n) AREA 
Atributos 
 LATITUD: 26.816668 
 LONGITUD: 38.7 
 FEATUREDESIGNATION: LCTY 
 COUNTRY: PO 
 NAMETYPE: N 
 FC: L 
Tiene 

NIL
"Porto da Calheta"
"Descripcion:"
|PORTO DA CALHETA| is a(n) AREA 
Atributos 
 LATITUD: 24.345833 
 LONGITUD: 37.740276 
 FEATUREDESIGNATION: PRT 
 COUNTRY: PO 
 NAMETYPE: N 
 FC: L 
Tiene 

NIL
"Porto Pim"
"Descripcion:"
|PORTO PIM| is a(n) AREA 
Atributos 
 LATITUD: 27.370832 
 LONGITUD: 38.525 
 FEATUREDESIGNATION: PRT 
 COUNTRY: PO 
 NAMETYPE: N 
 FC: L 
Tiene 

NIL
"Canada da Fonte"
"Descripcion:"
|CANADA DA FONTE| is a(n) AREA 
Atributos 
 LATITUD: 26.883333 
 LONGITUD: 38.733334 
 FEATUREDESIGNATION: LCTY 
 COUNTRY: PO 
 NAMETYPE: N 
 FC: L 
Tiene 

NIL
"Porto Judeu"
"Descripcion:"
|PORTO JUDEU| is a(n) AREA 
Atributos 
 LATITUD: 26.866667 
 LONGITUD: 38.65 
 FEATUREDESIGNATION: PRT 
 COUNTRY: PO 
 NAMETYPE: N 
 FC: L 
Tiene 

NIL

+ Which political entities are 10 degrees from Madrid?

"Madrid"
"Descripcion:"
MADRID is a(n) PLACE 
Atributos 
 LATITUD: 2.3166666 
 LONGITUD: 40.4 
 FEATUREDESIGNATION: PPLC 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: P 
Tiene 

NIL

"Arrondissement de Wissembourg"
"Descripcion:"
|ARRONDISSEMENT DE WISSEMBOURG| is a(n) ADMINISTRATIVE 
Atributos 
 LATITUD: 7.9166665 
 LONGITUD: 48.916668 
 FEATUREDESIGNATION: ADM3 
 COUNTRY: FR 
 NAMETYPE: N 
 FC: A 
Tiene 

NIL
"Arrondissement de Haguenau"
"Descripcion:"
|ARRONDISSEMENT DE HAGUENAU| is a(n) ADMINISTRATIVE 
Atributos 
 LATITUD: 7.75 
 LONGITUD: 48.833332 
 FEATUREDESIGNATION: ADM3 
 COUNTRY: FR 
 NAMETYPE: N 
 FC: A 
Tiene 

NIL
"Arrondissement de Strasbourg-Campagne"
"Descripcion:"
|ARRONDISSEMENT DE STRASBOURG-CAMPAGNE| is a(n) ADMINISTRATIVE 
Atributos 
 LATITUD: 7.5833335 
 LONGITUD: 48.666668 
 FEATUREDESIGNATION: ADM3 
 COUNTRY: FR 
 NAMETYPE: N 
 FC: A 
Tiene 

NIL
"Arrondissement d' Erstein"
"Descripcion:"
|ARRONDISSEMENT D' ERSTEIN| is a(n) ADMINISTRATIVE 
Atributos 
 LATITUD: 7.5833335 
 LONGITUD: 48.416668 
 FEATUREDESIGNATION: ADM3 
 COUNTRY: FR 
 NAMETYPE: N 
 FC: A 
Tiene 

NIL
"Arrondissement de Sarreguemines"
"Descripcion:"
|ARRONDISSEMENT DE SARREGUEMINES| is a(n) ADMINISTRATIVE 
Atributos 
 LATITUD: 7.3333335 
 LONGITUD: 49.833332 
 FEATUREDESIGNATION: ADM3 
 COUNTRY: FR 
 NAMETYPE: N 
 FC: A 
Tiene 

NIL

+ Which spots are 5 degrees from Sevilla?

"SEVILLA"
"Descripcion:"
SEVILLA is a(n) PLACE 
Atributos 
 LATITUD: 4.013056 
 LONGITUD: 37.377224 
 FEATUREDESIGNATION: PPL 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: P 
Tiene 

NIL

"Marina di Cargèse"
"Descripcion:"
|MARINA DI CARGÈSE| is a(n) SPOT 
Atributos 
 LATITUD: 8.598889 
 LONGITUD: 42.13111 
 FEATUREDESIGNATION: MAR 
 COUNTRY: FR 
 NAMETYPE: N 
 FC: S 
Tiene 

NIL
"Rocca Marina"
"Descripcion:"
|ROCCA MARINA| is a(n) SPOT 
Atributos 
 LATITUD: 8.614445 
 LONGITUD: 42.13389 
 FEATUREDESIGNATION: MAR 
 COUNTRY: FR 
 NAMETYPE: N 
 FC: S 
Tiene 

NIL
"Ermita de San Simón"
"Descripcion:"
|ERMITA DE SAN SIMÓN| is a(n) SPOT 
Atributos 
 LATITUD: 2.45 
 LONGITUD: 41.533333 
 FEATUREDESIGNATION: HERM 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: S 
Tiene 

NIL

"Estación Empalme"
"Descripcion:"
|ESTACIÓN EMPALME| is a(n) SPOT 
Atributos 
 LATITUD: 2.6833334 
 LONGITUD: 41.766666 
 FEATUREDESIGNATION: RSTN 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: S 
Tiene 

NIL

"Ermita Alto de San Mateo"
"Descripcion:"
|ERMITA ALTO DE SAN MATEO| is a(n) SPOT 
Atributos 
 LATITUD: 2.3333333 
 LONGITUD: 41.533333 
 FEATUREDESIGNATION: HERM 
 COUNTRY: SP 
 NAMETYPE: N 
 FC: S 
Tiene 

NIL