2011-11-22 29 views
15

Migrando de DTD a XSD y, por alguna razón, la transición es muy accidentada. Entiendo cómo definir el esquema una vez que estoy dentro de la etiqueta raíz <xs:schema>, pero pasar el encabezado & cosas de declaración de espacio de nombres me resulta especialmente confuso.Encabezado y espacio de nombre de esquema XML Config

He estado tratando de seguir el tutorial bien diseñado en W3S pero incluso ese tutorial parece asumir un montón de conocimiento por adelantado.

Creo que lo que estoy buscando es la explicación de un Rey Inglés de qué atributos hacen lo que, a dónde van y por qué:

  • xmlns
  • xmlns: xs
  • xmlns: xsi
  • targetNamespace
  • xsi: schemaLocation

Y en En algunos casos veo diferentes variaciones de estos elementos/atributos, como xsi que parece tener dos notaciones diferentes, como xsi:schemaLocation="..." y xs:import schemaLocation="...".

Supongo que entre todas estas pequeñas variaciones parece que no puedo entender lo que hace cada una de ellas. ¡Gracias de antemano por aportar claridad a esta confusión!

Respuesta

56

Lo primero que debe entender es espacios de nombres XML. Si tiene algo de tiempo para perder, puede leer the specification. Encontré que esta es una de las especificaciones más claras relacionadas con XML. No importa si no entiendes todo lo que dice, es una buena base. Pero aquí hay un resumen rápido.

Los elementos y atributos XML tienen un nombre. Cuando veas <test att="hello"/>, estás viendo un elemento con el nombre "prueba", en el cual tenemos un atributo con el nombre "att". Pero esta no es la historia completa ...

XML es una sintaxis que le permite mezclar contenido de diferentes lenguajes de marcado. Por ejemplo, al usar XSLT para convertir un documento XML en una página XHTML, se trata de al menos tres lenguajes de marcado definidos en XML: sus documentos de entrada, XSLT y XHTML. Tales mezclas serían bastante difíciles si cada uno reservara sus propios nombres de elementos/atributos y nunca se permitieran las colisiones.

Ingrese espacios de nombres XML. Un espacio de nombre XML define una "esfera" dentro de la cual los nombres de elementos y atributos tienen una semántica real. El elemento "plantilla" tiene un significado bien definido en el espacio de nombres XSLT. El elemento "complexType" tiene un significado bien definido en el espacio de nombres del esquema XML. Si desea usar su propio lenguaje de marcado usando XML, entonces es posible siempre que lo haga en un espacio de nombre diferente.

Para asegurarse de que un espacio de nombres sea único, deberá proporcionar un identificador único. La especificación se estableció en el uso de URI, la mayoría de las veces en forma de una URL HTTP. La razón de esto es simple: tales URL tienden a ser buenos identificadores únicos. Pero también es una causa muy común de confusión porque las personas piensan que las URL realmente tienen un significado o se accederá a ellas a través de la red durante el procesamiento de XML. ¡Sepa muy bien que este no es el caso! La URL no es necesaria para apuntar a ningún recurso existente. No sufrirá ninguna transformación ni se resolverá en una dirección de red.Incluso si dos URL apuntan exactamente a lo mismo, en el momento en que difieren en un carácter, se consideran espacios de nombres diferentes. Un identificador de espacio de nombres es solo una cadena, y uno sensible a mayúsculas y minúsculas. Nada mas.

Con la introducción de los espacios de nombres, el nombre de un elemento o atributo XML de repente consta de dos partes: un espacio de nombres y un nombre local. Esa "prueba" en <test/> es solo el nombre local. El llamado "nombre totalmente calificado" consiste en una combinación algo invisible del espacio de nombres y el nombre local. A veces se utiliza la notación {namespace URI}local-name, pero eso no es más que una convención.

Así que ahora tenemos que ser capaces de usar espacios de nombres en un documento XML. Para declarar un espacio de nombre, XML tiene un mecanismo codificado. Utiliza la cadena especial xmlns para permitir que se realicen las declaraciones del espacio de nombres. Se puede hacer de una de estas dos maneras: vinculando el espacio de nombres a un prefijo o declarándolo como el espacio de nombre predeterminado.

Cuando se vincula a un prefijo, el formulario es algo como esto: xmlns:prefix="namespace URI". He aquí un ejemplo de un documento XML:

<foo:root xmlns:foo="http://www.foo.com"> 
    <foo:test /> 
</foo:root> 

Ahora hemos obligados espacio de nombres http://www.foo.com al prefijo foo. Dondequiera que este prefijo se ponga delante del nombre de un elemento o atributo, estamos afirmando que son parte de ese espacio de nombres.

Lo que es muy importante tener en cuenta aquí es que el prefijo real no significa absolutamente nada. El siguiente documento XML es semánticamente el mismo:

<bar:root xmlns:bar="http://www.foo.com"> 
    <bar:test /> 
</bar:root> 

El prefijo es simplemente una forma conveniente de representar el espacio de nombres. Nos ahorra tener que usar el URI por completo todo el tiempo.

El siguiente es el espacio de nombre predeterminado. Se puede declarar un espacio de nombre predeterminado con xmlns="namespace URI". En resumen, podría pensar que esto vincula un espacio de nombres al prefijo vacío. Una vez más el mismo documento XML, pero esta vez sin prefijos:

<root xmlns="http://www.foo.com"> 
    <test /> 
</root> 

Esto es un poco más conveniente para trabajar con. Entonces, ¿por qué tienen prefijos? Empiezan a jugar un papel cuando estamos mezclando el contenido de diferentes espacios de nombres:

<root xmlns="http://www.foo.com"> 
    <so:test xmlns:so="http://stackoverflow.com" /> 
</root> 

Esta vez se trata de un documento XML diferente. Nuestro elemento root se encuentra en el espacio de nombre http://www.foo.com, pero el elemento test se encuentra en http://stackoverflow.com porque hemos vinculado al prefijo so y lo usamos en test.

También observa aquí que los espacios de nombres se pueden declarar en cualquier elemento en el documento XML. El alcance de esa declaración (y el enlace al prefijo si corresponde) se convierte entonces en ese elemento y su contenido.

Esto a veces puede volverse confuso, incluso más ya que las declaraciones pueden anularse entre sí. Compruebe este documento:

<root xmlns="http://www.foo.com"> 
    <test /> 
    <so:test xmlns:so="http://www.stackoverflow.com" xmlns="http://www.bar.com"> 
     <test /> 
    </so:test> 
</root> 

tomar un momento y averiguar qué espacio de nombres cada elemento está en ... Es un buen ejercicio.

root está en el espacio de nombres http://www.foo.com.El primer elemento test también está en ese espacio de nombres, ya que no hemos usado un prefijo, pero estamos en el alcance de ese espacio de nombres predeterminado. El segundo elemento test con el prefijo so se encuentra en el espacio de nombres http://www.stackoverflow.com porque a eso es a lo que unimos el prefijo.

Entonces está el tercer elemento más interno, test. ¿En qué espacio de nombres está? No tiene un prefijo, por lo que debe estar en el espacio de nombres predeterminado. PERO, hemos cambiado nuestro espacio de nombres predeterminado en el segundo elemento de prueba. Entonces, ese elemento más interno pertenece al espacio de nombres http://www.bar.com, no a http://www.foo.com.

Confused yet? Simplemente recuerde lo siguiente:

  • Un espacio de nombre es solo una cadena. Los URI se utilizan como una forma conveniente de tener identificadores únicos.
  • Un prefijo se usa para representar un espacio de nombres, pero su nombre no tiene ningún significado. Solo piense en esto como un marcador de posición.
  • Puede establecer un espacio de nombre predeterminado. Todos los elementos dentro de su alcance que no tienen un prefijo se vuelven parte de él.

Uf. Ahora, en W3C XML Schema. ¿Cómo se relaciona todo esto con esto?

Bueno, para empezar, el esquema de XML es en sí mismo un lenguaje de marcado definido en XML. Por lo tanto, es lógico que obtenga su propio espacio de nombres. Y ese espacio de nombres es oficialmente http://www.w3.org/2001/XMLSchema. Si escribe ese S en minúsculas, está mal. ¿Empezando a ver por qué algunas personas realmente odian los espacios de nombres?

Los siguientes tres documentos son exactamente los mismos:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
</xsd:schema> 

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
</xs:schema> 

<schema xmlns="http://www.w3.org/2001/XMLSchema"> 
</schema> 

único que importa es que estamos utilizando la materia del espacio de nombres de esquema XML. Como una convención, sin embargo, las personas tienden a usar el prefijo xs o xsd en esquemas XML.

Cuando tenemos un documento XML, podemos desear especificar dónde están ubicados los esquemas. Más de un esquema puede ser relevante para un documento XML, porque como hemos establecido, los idiomas se pueden mezclar en XML. Para decir que un documento XML es una instancia de un esquema, una vez más hay un espacio de nombre especial disponible: http://www.w3.org/2001/XMLSchema-instance. Por convención, tendemos a vincular este espacio de nombres al prefijo xsi. Pero, nuevamente, esto no es obligatorio.

Hay un par de atributos definidos en ese espacio de nombres de instancia de esquema. Entre ellos están schemaLocation y noNamespaceSchemaLocation. Eche un vistazo a este documento:

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.foo.com/schema"> 
</root> 

¿Qué sucedió allí? Primero declaramos que estamos vinculando el prefijo xsi al espacio de nombres http://www.w3.org/2001/XMLSchema-instance. Luego, usamos un atributo dentro de ese espacio de nombres: noNamespaceSchemaLocation. Ese atributo nos dice dónde se encuentra el esquema para validar aquellas partes del documento que no se encuentran en ningún espacio de nombres en particular. El siguiente documento XML es exactamente el mismo, semánticamente:

<root xmlns:huh="http://www.w3.org/2001/XMLSchema-instance" huh:noNamespaceSchemaLocation="http://www.test.com/schema"> 
</root> 

Recuerde, los nombres de los prefijos no tienen significado. Ellos son marcadores de posición. Entonces, ¿qué pasa con ese atributo noNamespaceSchemaLocation? Básicamente, nos dice dónde podemos ubicar un esquema.Ahora, al contrario de lo que ocurre con un URI de espacio de nombres, esto definitivamente es algo que se puede usar para obtener elementos de una red o de un almacenamiento local. Un procesador XML que valide contra un esquema declarado en un documento podría intentar obtenerlo.

Luego está el hecho de que se llama noNamespaceSchemaLocation. Un esquema define un "espacio de nombres objetivo". Lo que hace es indicar en qué espacio de nombres forman parte los elementos y atributos que define. Pero el espacio de nombre de destino puede ser omitido. En ese caso, tenemos un esquema para documentos XML sin espacio de nombres. Tal esquema se puede consultar con noNamespaceSchemaLocation.

En muchos casos, un esquema realmente definirá un espacio de nombres. Para decir qué esquema pertenece a qué espacio de nombres, podemos usar otro atributo del espacio de nombres http://www.w3.org/2001/XMLSchema-instance: schemaLocation. Ese atributo puede contener pares (separados por espacios) de URI de espacio de nombres y URI de esquema. Supongamos que tenemos un esquema para el espacio de nombres http://www.foo.com ubicado en http://www.myschemas.com/foo-schema. A continuación, se puede afirmar que la siguiente manera:

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.foo.com http://www.myschemas.com/foo-schema"> 
</root> 

He aquí un ejemplo con múltiples pares de espacio de nombres en la localización:

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.foo.com http://www.myschemas.com/foo-schema http://www.bar.com http://www.randomschemas.com/bar-schema"> 
</root> 

Lo que hay que recordar aquí es que http://www.w3.org/2001/XMLSchema-instance material es para uso en documentos XML que son instancias de esquemas. El espacio de nombres http://www.w3.org/2001/XMLSchema es el que se utiliza para definir esquemas.


Así que ahora estamos hasta el cuello en URI y atributos de aspecto extraño con significados especiales. Eso es lo que ocurre con los espacios de nombres: se ven muy complejos hasta que descubres lo simples que son. Simplemente observe de cerca qué prefijo está ligado a qué URI de espacio de nombres, y sepa qué define ese URI.

Hay dos cosas más sobre los esquemas que necesito abordar para su pregunta: xs:import y xs:include. Observe cómo he usado la convención de prefijo xs aquí, ya que estamos hablando de W3C XML Schema.

El elemento include se puede usar para combinar los esquemas con el mismo espacio de nombres de destino. Básicamente nos permite modular esquemas en partes más pequeñas y juntarlos.

El elemento de importación hace una especie de lo mismo, pero para los esquemas con diferentes espacios de nombres de destino. Esto nos permite combinar esquemas para diferentes lenguajes de marcado.


Así que para recapitular:

  • xmlns: se utiliza para especificar un espacio de nombres predeterminado.
  • xmlns:prefix: se utiliza para enlazar un espacio de nombre a prefix.
  • http://www.w3.org/2001/XMLSchema: el espacio de nombres para el Esquema XML. Por convención a menudo obligado al prefijo xs, pero esto no es obligatorio ni se realiza automáticamente.
  • http://www.w3.org/2001/XMLSchema-instance: el espacio de nombre que define un conjunto de elementos útiles para declarar los detalles de cómo un documento XML es una instancia de un esquema. Por convención a menudo obligado al prefijo xsi, pero esto no es obligatorio ni se realiza automáticamente.
  • targetNamespace: un atributo que se puede usar en el Esquema XML (en el elemento raíz) para especificar para qué espacio de nombres se trata de una definición de esquema.
  • schemaLocation: uno de los atributos definidos por el espacio de nombres http://www.w3.org/2001/XMLSchema-instance, utilizado para indicar dónde se pueden encontrar uno o más esquemas para uno o más espacios de nombres.

Mi consejo final: encuentre una forma conveniente de validar documentos contra esquemas y juegue un poco. Experimente con espacios de nombres, incluye e importa. Cree documentos utilizando múltiples espacios de nombres y pruebe el alcance.

Después de eso, verifique las especificaciones de XML en sí, espacios de nombres XML y Esquema XML. Es una lectura hardcore, pero si avanzas en ella comprenderás que mucha gente todavía parece extrañar después de años de usar XML. Eventualmente todo tendrá sentido.

¡Buena suerte!

+3

Esto es épico: debería ser la respuesta definitiva a este tipo de preguntas, si el desbordamiento de pila admite esta característica. Gracias por publicar esto, aprendí mucho y puedo ver por qué mi respuesta fue limitada. –

+0

@hugh Ni siquiera está completo ... Para los atributos, los prefijos tienen reglas un tanto diferentes. No están calificados por defecto. Pero no estoy del todo seguro de si eso los coloca en el espacio de nombres del elemento o no, así que tengo cuidado de hacer declaraciones al respecto. Y hay más cosas que podría haber mencionado, pero la verdad es que solo las especificaciones pueden proporcionar respuestas definitivas. –

+0

G_H es extremadamente raro que alguien se tome el tiempo de responder a una pregunta tan completamente como esta. ¡Gracias! – IAmYourFaja

2

En respuesta a sus consultas:

  1. xmlns - un valor único que se utiliza en documentos de instancia para indicar qué esquema XML es un ejemplo de (o qué esquema se validará en contra). Aunque el espacio de nombres no identifica el archivo de esquema real, debe haber un esquema que defina este espacio de nombres.
  2. xmlns:xs - llamada prefijos de espacio de nombres y por convención utilizada en documentos de instancia para indicar dónde los tipos utilizados en el XML están viniendo. Puede pensar en esto como using en C# o imports en VB. Por ejemplo, xmlns:xs="http://mySharedTypes" dice que en este XML algunos de mis tipos provienen del espacio de nombres "http: // mySharedTypes", y estos tipos tendrán el prefijo "xs".
  3. xmlns:xsi - como arriba. De hecho, los prefijos xs y xsi son, por convención, utilizados al hacer referencia a los espacios de nombres del esquema W3C http://www.w3.org/2001/XMLSchema y http://www.w3.org/2001/XMLSchema-instance. Sin embargo, estos prefijos de espacio de nombres son solo convencionales y en realidad pueden ser cualquier cosa.
  4. targetNamespace - un valor único que pone en la definición del esquema que le da a los tipos que define en el esquema su espacio de nombre. Entonces, si alguien quiere usar los tipos en su esquema, entonces debe incluir un atributo xmlns con los mismos valores que su targetNamespace.
  5. xs:import schemaLocation - Tradicionalmente, esta es una ruta relativa a otro esquema, aunque no todos los procesadores xml lo reconocen. De modo que puede vincular opcionalmente a otro esquema en su xs:import como una especie de acceso directo al archivo de esquema en sí. El otro atributo en la importación es el esquema targetNamespace, que es obligatorio.
  6. xsi:schemaLocation - Aunque comparte el mismo nombre que el atributo de importación, no es la misma definición. Por convención, el prefijo de espacio de nombres xsi se refiere a los tipos del espacio de nombres http://www.w3.org/2001/XMLSchema-instance, que se usan dentro de los documentos de instancia, en lugar de los documentos de esquema.

Disculpa si lo anterior no está claro, es una pregunta un tanto abierta y hay mucho material que puedes escribir para cualquiera de estos puntos. Si necesita claridad sobre alguno de los puntos, pregunte: con gusto lo proporcionaré o, alternativamente, crearé una nueva pregunta con un alcance más restringido.

+0

Esta información no es del todo precisa. 'xmlns' indica un espacio de nombre predeterminado, no tiene nada que ver con la indicación de un esquema. Hay algunos otros errores. Pueden ser menores, pero cuando se trata de espacios de nombres y XML Schema, lo más pequeño puede convertirse rápidamente en algo confuso. –

+0

Muchas gracias hugh; esta es la mejor, más completa y fácil de entender explicación de estas cosas que he encontrado. Un último pensamiento: ¿y si está construyendo XML compatible con el esquema sobre la marcha (en la memoria, como, por ejemplo, una cadena): siempre necesita poner este xmlns, xs, xsi, etc. cosas en la "cadena de instancia" para validarlo, o es posible decirle a un analizador en qué esquema validar XML; luego para incluir todas esas definiciones en el esquema? – IAmYourFaja

+0

@G_H Gracias por tu comentario. Por favor, siéntase libre de editar mi respuesta o por favor indique otras imprecisiones y la incorporaré en mi respuesta. –

0
  • xmlns="uri1" y xmlns:whatever="uri2" son un nodo de espacio de nombres y no atributos. Su función es decir que cuando vea un elemento en su documento XML llamado whatever:myElement, el elemento pertenece al espacio de nombres "whatever". Este "espacio de nombres" se identifica por el uri declarado en el nodo de espacio de nombres.
  • targetNamespace es un atributo. Contiene un URI que identifica los elementos, tipos y grupos que define en su esquema.
  • xsi: schemaLocation es bastante diferente. Es un atributo que permite a los analizadores XML encontrar el esquema adjunto a una instancia XML. No lo necesitas en el esquema.
  • Con xs:import puede importar esquemas de diferentes espacios de nombres para usar sus elementos y tipos en su propio esquema. Al usar xs:import, el esquema importado y el esquema de importación deben tener un espacio de nombre diferente. Use xs:include si es el mismo espacio de nombres.
Cuestiones relacionadas