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!
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. –
@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. –
G_H es extremadamente raro que alguien se tome el tiempo de responder a una pregunta tan completamente como esta. ¡Gracias! – IAmYourFaja