JavaRush /Blog Java /Random-ES /Conceptos básicos de XML para programadores Java. Parte 2...
Ярослав
Nivel 40
Днепр

Conceptos básicos de XML para programadores Java. Parte 2 de 3

Publicado en el grupo Random-ES

Introducción

Hola, queridos lectores de mi artículo. Este es el segundo artículo de la serie sobre XML y hablará sobre el espacio de nombres XML y el esquema XML.
Conceptos básicos de XML
Hasta hace poco yo no sabía nada de esto, pero domino mucho material e intentaré explicar estos dos temas importantes con palabras sencillas. Quiero decir de inmediato que los esquemas son un mecanismo muy avanzado para validar documentos XML y son mucho más funcionales que los DTD, por lo que no haremos un estudio completo de ellos aquí. Empecemos :)

Espacio de nombres XML

Namespace significa “espacio de nombres”, sin embargo, en este artículo a menudo reemplazaré la expresión rusa con simplemente namespace, porque es más corta y más conveniente de entender. XML Namespace es una tecnología cuyo objetivo principal es garantizar que todos los elementos sean únicos en un archivo XML y no haya confusión. Y como se trata de cursos de Java, la misma tecnología también está disponible en paquetes de Java. Si pudiéramos poner dos clases con el mismo nombre una al lado de la otra y usarlas, ¿cómo determinaríamos qué clase necesitamos? Este problema se resuelve con paquetes: simplemente podemos colocar clases en diferentes paquetes e importarlas desde allí, especificando el nombre exacto del paquete deseado y la ruta al mismo, o simplemente especificando la ruta completa a la clase deseada. Conceptos básicos de XML para programadores Java.  Parte 2 de 3 - 1Ahora podemos hacer esto:
public class ExampleInvocation {
    public static void main(String[] args) {
        // Creación экземпляра класса из первого пакета.
        example_package_1.Example example1 = new example_package_1.Example();

        // Creación экземпляра класса из второго пакета.
        example_package_2.Example example2 = new example_package_2.Example();

        // Creación экземпляра класса из третьего пакета.
        example_package_3.Example example3 = new example_package_3.Example();
    }
}
En XML Namespace todo es más o menos igual, sólo que un poco diferente. La esencia es la misma: si los elementos son iguales (como clases), entonces solo tenemos que usarlos en diferentes espacios de nombres (especificar paquetes), incluso si los nombres de los elementos (clases) comienzan a coincidir, seguiremos acceder a un elemento específico desde el espacio (paquete). Por ejemplo: tenemos dos elementos en XML: predicción (oracle) y base de datos Oracle.
<?xml version="1.0" encoding="UTF-8"?>
<root>
    <oracle>
        <connection value="jdbc:oracle:thin:@10.220.140.48:1521:test1" />
        <user value="root" />
        <password value="111" />
    </oracle>

    <oracle>
        Сегодня вы будете заняты весь день.
    </oracle>
</root>
Y cuando procesamos este archivo XML, nos sentiremos seriamente confundidos si en lugar de la base de datos recibimos una predicción y viceversa. Para resolver la colisión de elementos, podemos asignar a cada uno de ellos su propio espacio para diferenciarlos. Hay un atributo especial para esto: xmlns:prefix= “valor único para el espacio de nombres”. Luego podemos prefijar los elementos para indicar que es parte de ese espacio de nombres (esencialmente, tenemos que crear una ruta de paquete - espacio de nombres, y luego prefijar cada elemento con el paquete al que pertenece).
<?xml version="1.0" encoding="UTF-8"?>
<root>
    <database:oracle xmlns:database="Unique ID #1">
        <connection value="jdbc:oracle:thin:@10.220.140.48:1521:test1" />
        <user value="root" />
        <password value="111" />
    </database:oracle>

    <oracle:oracle xmlns:oracle="Unique ID #2">
        Сегодня вы будете заняты весь день.
    </oracle:oracle>
</root>
En este ejemplo, hemos declarado dos espacios de nombres: base de datos y Oracle. Ahora puedes usar prefijos de espacios de nombres antes de los elementos. No hay por qué asustarse si algo no está claro ahora. De hecho, es muy simple. Al principio quería escribir esta parte del artículo más rápido, pero después del miércoles decidí que necesitaba prestar más atención a este tema, ya que es fácil confundirse o no entender algo. Ahora se prestará mucha atención al atributo xmlns. Y así, otro ejemplo:
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="https://www.standart-namespace.com/" xmlns:gun="https://www.gun-shop.com/" xmlns:fish="https://www.fish-shop.com/">
    <gun:shop>
        <gun:guns>
            <gun:gun name="Revolver" price="1250$" max_ammo="7" />
            <gun:gun name="M4A1" price="3250$" max_ammo="30" />
            <gun:gun name="9mm Pistol" price="450$" max_ammo="12" />
        </gun:guns>
    </gun:shop>

    <fish:shop>
        <fish:fishes>
            <fish:fish name="Shark" price="1000$" />
            <fish:fish name="Tuna" price="5$" />
            <fish:fish name="Capelin" price="1$" />
        </fish:fishes>
    </fish:shop>
</root>
Puede ver el XML normal utilizando los elementos únicos de la tienda de armas de espacios y elementos únicos de la tienda de peces para pescar. Puedes ver que al crear los espacios, usamos un elemento de tienda para dos cosas diferentes a la vez: una tienda de armas y una pescadería, y sabemos exactamente qué tipo de tienda es gracias al hecho de que declaramos los espacios. Lo más interesante comenzará en los esquemas, cuando de esta forma podremos validar diferentes estructuras con los mismos elementos. xmlns es un atributo para declarar un espacio de nombres; se puede especificar en cualquier elemento. Un ejemplo de una declaración de espacio de nombres:
xmlns:shop= «https://barber-shop.com/»
Después de los dos puntos hay un prefijo: esta es una referencia de espacio que luego se puede usar antes de los elementos para indicar que provienen de ese espacio. El valor xmlns debe ser una CADENA ÚNICA. Es extremadamente importante comprender esto: es muy común utilizar enlaces a sitios web o URI para declarar un espacio de nombres. Esta regla es estándar porque el URI o URL del enlace es único, PERO aquí es donde se vuelve muy confuso. Solo recuerde: el valor puede ser CUALQUIER cadena que desee, pero para asegurarse de que sea único y estándar, debe usar una URL o URI. El hecho de que puede utilizar cualquier cadena se muestra en el ejemplo de Oracle:
xmlns:oracle="Unique ID #2"
xmlns:database="Unique ID #1"
Cuando declaras un espacio de nombres, puedes usarlo en el elemento mismo y en todos los elementos dentro de él, por lo que los espacios de nombres declarados en el elemento raíz se pueden usar en todos los elementos. Esto se puede ver en el último ejemplo, y aquí hay un ejemplo más específico:
<?xml version="1.0" encoding="UTF-8"?>
<root>
    <el1:element1 xmlns:el1="Element#1 Unique String">
        <el1:innerElement>

        </el1:innerElement>
    </el1:element1>


    <el2:element2 xmlns:el2="Element#2 Unique String">
        <el2:innerElement>

        </el2:innerElement>
    </el2:element2>


    <el3:element3 xmlns:el3="Element#3 Unique String">
        <el3:innerElement>
            <el1:innerInnerElement> <!-- Так нельзя, потому что пространство el1 объявлено только в первом элементе, потому может использовать только внутри первого elemento и его внутренних элементов. -->

            </el1:innerInnerElement>
        </el3:innerElement>
    </el3:element3>
</root>
Aquí hay un detalle importante: también hay un espacio de nombres estándar en el elemento raíz. Si declara otros espacios de nombres, anula el predeterminado y no puede usarlo. Luego, debes colocar algún tipo de prefijo de espacio delante del elemento raíz, cualquiera que hayas declarado anteriormente. Sin embargo, esto también puede ser engañoso: puedes declarar el espacio estándar explícitamente. Es suficiente simplemente no usar un prefijo después de xmlns, sino escribir inmediatamente algún valor, y todos sus elementos sin prefijo pertenecerán a este espacio de nombres en particular. El último ejemplo usó esto:
<root xmlns="https://www.standart-namespace.com/" xmlns:gun="https://www.gun-shop.com/" xmlns:fish="https://www.fish-shop.com/">
Declaramos el espacio estándar explícitamente para evitar la necesidad de usar arma o pez, ya que el elemento raíz no es la entidad ni de una tienda de pesca ni de un arma, por lo que usar cualquiera de los espacios sería lógicamente incorrecto. Siguiente: si creó xmlns:a y xmlns:b, pero tienen el mismo valor, entonces este es el mismo espacio y no son únicos. Es por eso que siempre debes usar valores únicos, porque violar esta regla puede generar una gran cantidad de errores. Por ejemplo, si tuviéramos espacios declarados así:
xmlns="https://www.standart-namespace.com/" xmlns:gun="https://www.gun-shop.com/" xmlns:fish="https://www.gun-shop.com/"
Entonces nuestra tienda de pesca se convertiría en una tienda de armas y el prefijo seguiría siendo una tienda de pescado. Estos son todos los puntos principales de los espacios. Pasé bastante tiempo recopilándolos todos y reduciéndolos, y luego expresándolos claramente, ya que la información sobre los espacios en Internet es muy grande y a menudo solo agua, así que la mayor parte de todo lo que hay aquí, lo aprendí yo mismo a través de una prueba. y error. Si aún tiene preguntas, puede intentar leer los materiales utilizando los enlaces al final del artículo.

Esquema XML

Quiero decir de inmediato que este artículo será solo la punta del iceberg, ya que el tema es muy amplio. Si desea familiarizarse con los esquemas con más detalle y aprender a escribirlos usted mismo de cualquier complejidad, al final del artículo habrá un enlace donde se tratará todo sobre diferentes tipos, restricciones, extensiones, etc. Quiero empezar con la teoría. Los esquemas tienen el formato .xsd (definición de esquema xml) y son una alternativa más avanzada y popular a las DTD: también pueden crear elementos, describirlos, etc. Sin embargo, se han agregado muchas ventajas: verificación de tipos, compatibilidad con espacios de nombres y una funcionalidad más amplia. ¿Recuerdas que cuando hablamos de DTD había un inconveniente: no admite espacios? Ahora que hemos estudiado esto, lo explico: si fuera posible importar dos o más esquemas de una DTD, donde hubiera elementos idénticos, tendríamos colisiones (coincidencias) y no podríamos usarlos en absoluto, porque No está claro qué elemento necesitamos. XSD resuelve este problema porque puedes importar esquemas a un espacio específico y usarlo. Básicamente, cada esquema XSD tiene un espacio de destino, lo que significa en qué espacio se debe escribir el esquema en el archivo XML. Por lo tanto, en el archivo XML en sí, solo necesitamos crear estos espacios predefinidos en los esquemas y asignarles prefijos, y luego conectar los esquemas necesarios a cada uno de ellos, después de lo cual podemos usar de manera segura elementos del esquema, sustituyendo los prefijos de el espacio donde importamos los esquemas. Y así, tenemos un ejemplo:
<?xml version="1.0" encoding="UTF-8"?>
<house>
    <address>ул. Есенина, дом №5</address>
    <owner name="Ivan">
        <telephone>+38-094-521-77-35</telephone>
    </owner>
</house>
Queremos validarlo con un esquema. Primero, necesitamos un esquema:
<?xml version="1.0"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="https://www.nedvigimost.com/">
    <element name="house">
        <complexType>
            <sequence>
                <element name="address" type="string" maxOccurs="unbounded" minOccurs="0" />
                <element name="owner" maxOccurs="unbounded" minOccurs="0" >
                    <complexType>
                        <sequence>
                            <element name="telephone" type="string" />
                        </sequence>
                        <attribute name="name" type="string" use="required"/>
                    </complexType>
                </element>
            </sequence>
        </complexType>
    </element>
</schema>
Como puede ver, los esquemas también son archivos XML. Escribes lo que necesitas directamente en XML. Este esquema es capaz de validar el archivo XML del ejemplo anterior. Por ejemplo: si el propietario no tiene nombre, el circuito lo verá. Además, gracias al elemento de secuencia, siempre debe ir primero la dirección y luego el dueño de la casa. Hay elementos ordinarios y complejos. Los elementos regulares son elementos que almacenan solo algún tipo de datos. Ejemplo:
<element name="telephone" type="string" />
Así declaramos un elemento que almacena una cadena. No debería haber otros elementos dentro de este elemento. También hay elementos complejos. Los elementos complejos son capaces de almacenar otros elementos y atributos dentro de ellos mismos. Entonces no necesita especificar el tipo, simplemente comience a escribir un tipo complejo dentro del elemento.
<complexType>
    <sequence>
        <element name="address" type="string" maxOccurs="unbounded" minOccurs="0" />
        <element name="owner" maxOccurs="unbounded" minOccurs="0" >
            <complexType>
                <sequence>
                    <element name="telephone" type="string" />
                </sequence>
                <attribute name="name" type="string" use="required"/>
            </complexType>
        </element>
    </sequence>
</complexType>
También era posible hacerlo de otra manera: se podía crear un tipo complejo por separado y luego sustituirlo en el tipo. Solo que al escribir este ejemplo, por alguna razón fue necesario declarar el espacio bajo algún tipo de prefijo y no usar el estándar. En general, resultó así:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="https://www.nedvigimost.com/">
    <xs:element name="house" type="content" />

    <xs:complexType name="content">
        <xs:sequence>
            <xs:element name="address" type="xs:string" maxOccurs="unbounded" minOccurs="0" />
            <xs:element name="owner" maxOccurs="unbounded" minOccurs="0" >
                <xs:complexType>
                    <xs:sequence>
                        <xs:element name="telephone" type="xs:string" />
                    </xs:sequence>
                    <xs:attribute name="name" type="xs:string" use="required"/>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
    </xs:complexType>
</xs:schema>
De esta manera, podemos crear nuestros propios tipos por separado y luego sustituirlos en algún lugar del atributo de tipo. Esto es muy conveniente ya que le permite utilizar un tipo en diferentes lugares. Me gustaría hablar más sobre la conexión de circuitos y terminar aquí. Hay dos formas de conectar un circuito: en un espacio específico y simplemente conectarlo.

La primera forma de conectar el circuito.

El primer método supone que el circuito tiene un espacio objetivo específico. Se especifica utilizando el atributo targetNamespace en el elemento del esquema. Entonces basta con crear ESTE MISMO espacio en el archivo XML y luego “cargar” el esquema allí:
<?xml version="1.0" encoding="UTF-8"?>
<nedvig:house xmlns:nedvig="https://www.nedvigimost.com/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://www.nedvigimost.com/ example_schema1.xsd">
    <address>ул. Есенина, дом №5</address>
    <owner name="Ivan">
        <telephone>+38-094-521-77-35</telephone>
    </owner>
</nedvig:house>
Es importante entender dos líneas:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemeLocation="https://www.nedvigimost.com/ example_schema1.xsd"
La primera línea , solo recuérdala. Piense en ello como un objeto que ayuda a cargar esquemas donde deben ir. La segunda línea es una descarga específica. esquemaLocation acepta una lista de valores de la forma "valor - valor", separados por espacios. El primer argumento es el espacio de nombres, que debe coincidir con el espacio de nombres de destino en el esquema (el valor de targetNamespace). El segundo argumento es la ruta relativa o absoluta al esquema. Y dado que este es un valor de LISTA, puede colocar un espacio después del esquema en el ejemplo y nuevamente ingresar el espacio de destino y el nombre de otro esquema, y ​​así sucesivamente tanto como desee. Importante:Para que el esquema valide algo más adelante, debes declarar este espacio y usarlo con un prefijo. Mire atentamente el último ejemplo:
<?xml version="1.0" encoding="UTF-8"?>
<nedvig:house xmlns:nedvig="https://www.nedvigimost.com/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://www.nedvigimost.com/ example_schema1.xsd">
    <address>ул. Есенина, дом №5</address>
    <owner name="Ivan">
        <telephone>+38-094-521-77-35</telephone>
    </owner>
</nedvig:house>
Creamos este espacio de destino en el prefijo nedvig y luego lo usamos. Así, nuestros elementos comenzaron a ser validados, ya que comenzamos a utilizar el espacio donde se referencia el espacio del esquema de destino.

La segunda forma de conectar el circuito.

La segunda forma de conectar un circuito implica que el circuito no tiene un espacio objetivo específico. Luego simplemente puede conectarlo al archivo XML y lo validará. Esto se hace casi de la misma manera, solo que no puede declarar ningún espacio en el archivo XML, sino simplemente conectar el esquema.
<?xml version="1.0" encoding="UTF-8"?>
<house xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="example_schema1.xsd">
    <address>ул. Есенина, дом №5</address>
    <owner name="Ivan">
        <telephone>+38-094-521-77-35</telephone>
    </owner>
</house>
Como puede ver, esto se hace usando noNamespaceSchemaLocation y especificando la ruta al esquema. Incluso si el esquema no tiene un espacio de destino, el documento será validado. Y el toque final: podemos importar otros diagramas a diagramas y luego usar elementos de un diagrama en otro. Así, podemos utilizar elementos en algunos circuitos que ya están en otros. Ejemplo:

Esquema donde se declara el tipo de propietario:

<?xml version="1.0" encoding="UTF-8" ?>
<schema targetNamespace="bonus" xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
        <complexType name="owner">
            <all>
                <element name="telephone" type="string" />
            </all>
            <attribute name="name" type="string" />
        </complexType>
</schema>

El segundo esquema, que utiliza el tipo de propietario del primer esquema:

<?xml version="1.0" encoding="UTF-8"?>
<schema targetNamespace="main" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:bonus="bonus" elementFormDefault="qualified">
    <import namespace="bonus" schemaLocation="xsd2.xsd" />
    <element name="house">
        <complexType>
            <all>
              <element name="address" type="string" />
                <element name="owner" type="bonus:owner" />
            </all>
        </complexType>
    </element>
</schema>
El segundo esquema utiliza la siguiente construcción:
<import namespace="bonus" schemaLocation="xsd2.xsd" />
Al usarlo, importamos tipos y elementos de un esquema a otro al espacio de bonificación. Así, tenemos acceso al tipo bono:propietario. Y en la siguiente línea lo usamos:
<element name="owner" type="bonus:owner" />
También un poco de atención a la siguiente línea:
elementFormDefault="qualified"
Este atributo se declara en el esquema y significa que en los archivos XML, cada elemento debe declararse con un prefijo explícito antes. Si no está ahí, entonces solo necesitamos declarar un elemento externo con un prefijo, y también debemos establecer prefijos en todos los elementos internos, indicando claramente que estamos usando exactamente los elementos de este esquema. Y aquí, de hecho, hay un ejemplo de un archivo XML validado por un esquema que importó otro esquema:
<?xml version="1.0" encoding="UTF-8"?>
<nedvig:house xmlns:nedvig="main" xmlns:bonus="bonus" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="main xsd.xsd">
    <nedvig:address>ул. Есенина, дом №5</nedvig:address>
    <nedvig:owner name="Ivan">
        <bonus:telephone>+38-094-521-77-35</bonus:telephone>
    </nedvig:owner>
</nedvig:house>
En la linea:
<bonus:telephone>+38-094-521-77-35</bonus:telephone>
Necesitamos declarar explícitamente el espacio de nombres adicional, que apunta al espacio de destino del primer esquema, ya que elementFormDefault está calificado (verificar), por lo que todos los elementos deben indicar explícitamente su espacio.

Fin del artículo

El próximo artículo será el último de la serie y tratará sobre el procesamiento de archivos XML utilizando Java. Aprenderemos a obtener información de diferentes formas y así sucesivamente. Espero que este artículo haya sido útil e, incluso si hay errores en alguna parte, le enseñará algo nuevo y útil, o tal vez simplemente le brinde la oportunidad de comprender mejor los archivos XML. Para aquellos que quieran explorar esto con más detalle, decidí reunir un pequeño conjunto de enlaces:
  • XSD Simple Elements : a partir de este artículo, comience a leer y siga adelante, toda la información sobre los esquemas se recopila allí y se explica más o menos claramente, solo en inglés. Puedes utilizar un traductor.

  • vídeo sobre espacios de nombres, siempre es útil escuchar otro punto de vista sobre algo si el primero no está claro.

  • Namespace XML es un buen ejemplo del uso de espacios de nombres y es bastante completo.

  • Conceptos básicos de XML: espacios de nombres : otro breve artículo sobre espacios de nombres.

  • Los conceptos básicos del uso de esquemas XML para definir elementos también es una referencia extremadamente útil sobre esquemas, pero es necesario leerlo lenta y cuidadosamente, profundizando en el material.

Eso es todo seguro, espero que si quieres aprender algo más profundo de esto, los enlaces te ayuden. Yo mismo revisé todas estas fuentes, estudié todo el material y, en general, estas fueron las más útiles de todas las fuentes que miré, ya que cada una de ellas mejoró la comprensión de lo que ya había leído en otro lugar, o Déjame aprender algo nuevo, pero se hicieron muchas cosas solo durante la práctica. Entonces, para aquellos que realmente quieren entender todo esto bastante bien, mi consejo es: estudien los espacios de nombres, luego cómo conectar fácilmente esquemas a archivos XML y luego cómo escribir la estructura del documento en esquemas. Y lo más importante, practica. Gracias a todos por su atención y buena suerte en la programación :) Artículo anterior: [Concurso] Conceptos básicos de XML para un programador de Java - Parte 1 de 3 Artículo siguiente: [Concurso] Conceptos básicos de XML para un programador de Java - Parte 3.1 de 3 - SAX
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION