JavaRush /Java Blog /Random-IT /Nozioni di base su XML per programmatori Java. Parte 2 di...
Ярослав
Livello 40
Днепр

Nozioni di base su XML per programmatori Java. Parte 2 di 3

Pubblicato nel gruppo Random-IT

introduzione

Ciao, cari lettori del mio articolo. Questo è il secondo articolo della serie sull'XML e parlerà dello spazio dei nomi XML e dello schema XML.
Nozioni di base sull'XML
Proprio di recente, io stesso non ne sapevo nulla, ma ho imparato molto materiale e cercherò di spiegare questi due argomenti importanti in parole semplici. Voglio dire subito che gli schemi sono un meccanismo molto avanzato per convalidare i documenti XML e sono molto più funzionali dei DTD, quindi non ne tratteremo uno studio completo qui. Iniziamo :)

Spazio dei nomi XML

Namespace significa “namespace”, tuttavia in questo articolo sostituirò spesso l’espressione russa con semplicemente namespace, perché è più breve e più comodo da capire. XML Namespace è una tecnologia il cui scopo principale è garantire che tutti gli elementi siano univoci in un file XML e non vi sia confusione. E poiché si tratta di corsi Java, la stessa tecnologia è disponibile anche nei pacchetti Java. Se potessimo mettere due classi con lo stesso nome una accanto all'altra e usarle, come potremmo determinare di quale classe abbiamo bisogno? Questo problema viene risolto dai pacchetti: possiamo semplicemente posizionare le classi in diversi pacchetti e importarle da lì, specificando il nome esatto del pacchetto desiderato e il percorso ad esso, o semplicemente specificando il percorso completo della classe desiderata. Nozioni di base su XML per programmatori Java.  Parte 2 di 3 - 1Ora possiamo fare questo:
public class ExampleInvocation {
    public static void main(String[] args) {
        // Creation экземпляра класса из первого пакета.
        example_package_1.Example example1 = new example_package_1.Example();

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

        // Creation экземпляра класса из третьего пакета.
        example_package_3.Example example3 = new example_package_3.Example();
    }
}
Nello spazio dei nomi XML tutto è più o meno lo stesso, solo leggermente diverso. L'essenza è la stessa: se gli elementi sono gli stessi (come le classi), allora dobbiamo solo usarli in spazi dei nomi diversi (specificare i pacchetti), quindi anche se i nomi degli elementi (classi) iniziano a coincidere, lo faremo comunque accedere a un elemento specifico dallo spazio (pacchetto). Ad esempio: abbiamo due elementi in XML: previsione (Oracle) e database 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>
E quando elaboriamo questo file XML, rimarremo seriamente confusi se invece del database riceviamo una previsione, e viceversa. Per risolvere la collisione degli elementi, possiamo assegnare a ciascuno di essi il proprio spazio per distinguerli. Esiste un attributo speciale per questo: xmlns:prefix= “valore univoco per lo spazio dei nomi”. Possiamo quindi prefissare gli elementi per indicare che fa parte di quello spazio dei nomi (essenzialmente, dobbiamo creare un percorso del pacchetto - spazio dei nomi, e quindi prefissare ogni elemento con il pacchetto a cui appartiene).
<?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>
In questo esempio abbiamo dichiarato due spazi dei nomi: database e oracle. Ora puoi utilizzare i prefissi dello spazio dei nomi prima degli elementi. Non c'è bisogno di spaventarsi se adesso qualcosa non è chiaro. In effetti, è molto semplice. All'inizio volevo scrivere questa parte dell'articolo più velocemente, ma dopo mercoledì ho deciso che dovevo prestare maggiore attenzione a questo argomento, poiché è facile confondersi o non capire qualcosa. Ora verrà prestata molta attenzione all'attributo xmlns. E allora, un altro esempio:
<?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>
Puoi visualizzare l'XML normale utilizzando gli spazi pistola per elementi unici del negozio di armi e elementi unici del negozio di pesce per la pesca. Puoi vedere che creando gli spazi, abbiamo utilizzato un elemento del negozio per due cose diverse contemporaneamente: un negozio di armi e un negozio di pesce, e sappiamo esattamente che tipo di negozio è grazie al fatto che abbiamo dichiarato gli spazi. La cosa più interessante inizierà dagli schemi, quando in questo modo potremo validare diverse strutture con gli stessi elementi. xmlns è un attributo per dichiarare uno spazio dei nomi; può essere specificato in qualsiasi elemento. Un esempio di dichiarazione dello spazio dei nomi:
xmlns:shop= «https://barber-shop.com/»
Dopo i due punti c'è un prefisso: questo è un riferimento allo spazio che può quindi essere utilizzato prima degli elementi per indicare che provengono da quello spazio. Il valore xmlns deve essere una STRINGA UNICA. Questo è estremamente importante da capire: è molto comune utilizzare collegamenti a siti Web o URI per dichiarare uno spazio dei nomi. Questa regola è standard perché l'URI o l'URL del collegamento è univoco, MA è qui che diventa molto confusa. Ricorda solo: il valore può essere QUALSIASI stringa tu voglia, ma per essere sicuro che sia univoco e standard, devi utilizzare un URL o URI. Il fatto che sia possibile utilizzare qualsiasi stringa è mostrato nell'esempio in Oracle:
xmlns:oracle="Unique ID #2"
xmlns:database="Unique ID #1"
Quando dichiari uno spazio dei nomi, puoi usarlo sull'elemento stesso e su tutti gli elementi al suo interno, quindi gli spazi dei nomi dichiarati sull'elemento root possono essere usati su tutti gli elementi. Questo può essere visto nell'ultimo esempio, ed ecco un esempio più specifico:
<?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 объявлено только в первом элементе, потому может использовать только внутри первого element и его внутренних элементов. -->

            </el1:innerInnerElement>
        </el3:innerElement>
    </el3:element3>
</root>
Ecco un dettaglio importante: c'è anche uno spazio dei nomi standard nell'elemento root. Se dichiari altri spazi dei nomi, sovrascrivi quello predefinito e non puoi utilizzarlo. Quindi devi inserire una sorta di prefisso spaziale davanti all'elemento root, quello che hai dichiarato in precedenza. Tuttavia, questo può anche essere ingannato: puoi dichiarare esplicitamente lo spazio standard. Basta non usare il prefisso dopo xmlns, ma scrivere immediatamente un valore e tutti i tuoi elementi senza prefisso apparterranno a questo particolare spazio dei nomi. L'ultimo esempio ha utilizzato questo:
<root xmlns="https://www.standart-namespace.com/" xmlns:gun="https://www.gun-shop.com/" xmlns:fish="https://www.fish-shop.com/">
Abbiamo dichiarato esplicitamente lo spazio standard per evitare la necessità di utilizzare la pistola o il pesce, poiché l'elemento radice non è l'entità né di un negozio di pesca né di un'arma, quindi utilizzare uno dei due spazi sarebbe logicamente errato. Successivamente: se hai creato xmlns:a e xmlns:b, ma hanno lo stesso valore, allora si tratta dello stesso spazio e non sono univoci. Ecco perché dovresti utilizzare sempre valori univoci, perché la violazione di questa regola può creare un gran numero di errori. Ad esempio, se avessimo spazi dichiarati in questo modo:
xmlns="https://www.standart-namespace.com/" xmlns:gun="https://www.gun-shop.com/" xmlns:fish="https://www.gun-shop.com/"
Quindi il nostro negozio di pesca diventerebbe un negozio di armi e il prefisso sarebbe ancora un negozio di pesce. Questi sono tutti i punti principali degli spazi. Ho passato parecchio tempo a raccoglierli tutti e ridurli, per poi esprimerli chiaramente, poiché le informazioni sugli spazi su Internet sono molto grandi e spesso solo acqua, quindi la maggior parte di tutto ciò che è qui - l'ho imparato io stesso attraverso le prove ed errore. Se hai ancora domande, puoi provare a leggere i materiali utilizzando i collegamenti alla fine dell'articolo.

Schema XML

Voglio dire subito che questo articolo sarà solo la punta dell'iceberg, poiché l'argomento è molto ampio. Se vuoi conoscere gli schemi in modo più dettagliato e imparare come scriverli tu stesso di qualsiasi complessità, alla fine dell'articolo ci sarà un collegamento in cui tutto riguarderà diversi tipi, restrizioni, estensioni e così via. Voglio iniziare con la teoria. Gli schemi hanno il formato .xsd (xml schema definizione) e sono un'alternativa più avanzata e popolare ai DTD: possono anche creare elementi, descriverli e così via. Tuttavia, sono stati aggiunti molti bonus: controllo del tipo, supporto dello spazio dei nomi e funzionalità più ampie. Ricordi quando abbiamo parlato di DTD, c'era uno svantaggio che non supporta gli spazi? Ora che abbiamo studiato questo, mi spiego: se fosse possibile importare due o più schemi da un DTD, dove ci fossero elementi identici, avremmo delle collisioni (coincidenze) e non potremmo utilizzarli affatto, perché non è chiaro di quale elemento abbiamo bisogno. XSD risolve questo problema perché puoi importare schemi in uno spazio specifico e utilizzarlo. In sostanza, ogni schema XSD ha uno spazio di destinazione, il che significa in quale spazio lo schema deve essere scritto nel file XML. Pertanto, nel file XML stesso, dobbiamo solo creare questi spazi predefiniti negli schemi e assegnare loro dei prefissi, quindi collegare gli schemi necessari a ciascuno di essi, dopodiché possiamo tranquillamente utilizzare gli elementi dello schema, sostituendo i prefissi da lo spazio in cui abbiamo importato gli schemi. E quindi, abbiamo un esempio:
<?xml version="1.0" encoding="UTF-8"?>
<house>
    <address>ул. Есенина, дом №5</address>
    <owner name="Ivan">
        <telephone>+38-094-521-77-35</telephone>
    </owner>
</house>
Vogliamo validarlo con uno schema. Innanzitutto, abbiamo bisogno di uno schema:
<?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>
Come puoi vedere, anche gli schemi sono file XML. Scrivi ciò che ti serve direttamente in XML. Questo schema è in grado di convalidare il file XML dell'esempio precedente. Ad esempio: se il proprietario non ha un nome, il circuito lo vedrà. Inoltre, grazie all'elemento sequenza, dovrebbe sempre venire prima l'indirizzo e poi il proprietario della casa. Ci sono elementi ordinari e complessi. Gli elementi regolari sono elementi che memorizzano solo alcuni tipi di dati. Esempio:
<element name="telephone" type="string" />
Questo è il modo in cui dichiariamo un elemento che memorizza una stringa. Non dovrebbero esserci altri elementi all'interno di questo elemento. Ci sono anche elementi complessi. Gli elementi complessi sono in grado di memorizzare altri elementi e attributi al loro interno. Quindi non è necessario specificare il tipo, ma basta iniziare a scrivere un tipo complesso all'interno dell'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>
Era anche possibile farlo diversamente: si poteva creare un tipo complesso separatamente e poi sostituirlo nel tipo. Solo durante la scrittura di questo esempio, per qualche motivo è stato necessario dichiarare lo spazio con un qualche tipo di prefisso e non utilizzare quello standard. In generale, è risultato così:
<?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>
In questo modo possiamo creare i nostri tipi separatamente e poi sostituirli da qualche parte nell'attributo type. Questo è molto comodo in quanto ti consente di utilizzare un tipo in luoghi diversi. Vorrei parlare più approfonditamente del collegamento dei circuiti e concludere qui. Esistono due modi per collegare un circuito: in uno spazio specifico e semplicemente connettersi.

Il primo modo per collegare il circuito

Il primo metodo presuppone che il circuito abbia uno spazio target specifico. Viene specificato utilizzando l'attributo targetNamespace sull'elemento schema. Quindi è sufficiente creare QUESTO STESSO spazio nel file XML e quindi "caricare" lì lo schema:
<?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>
È importante comprendere due linee:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemeLocation="https://www.nedvigimost.com/ example_schema1.xsd"
La prima riga : ricordala e basta. Consideratelo come un oggetto che aiuta a caricare gli schemi dove devono andare. La seconda riga è un download specifico. schemaLocation accetta un elenco di valori nella forma "valore - valore", separati da spazi. Il primo argomento è lo spazio dei nomi, che deve corrispondere allo spazio dei nomi di destinazione nello schema (il valore targetNamespace). Il secondo argomento è il percorso relativo o assoluto allo schema. E poiché questo è un valore LISTA, puoi inserire uno spazio dopo lo schema nell'esempio, quindi inserire nuovamente lo spazio di destinazione e il nome di un altro schema, e così via quanto vuoi. Importante:Affinché lo schema possa convalidare qualcosa in seguito, è necessario dichiarare questo spazio e utilizzarlo con un prefisso. Osserva attentamente l'ultimo esempio:
<?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>
Abbiamo creato questo spazio di destinazione sul prefisso nedvig e poi lo abbiamo utilizzato. Pertanto, i nostri elementi hanno iniziato a essere convalidati, poiché abbiamo iniziato a utilizzare lo spazio in cui viene fatto riferimento allo spazio dello schema di destinazione.

Il secondo modo per collegare il circuito

Il secondo modo per connettere un circuito implica che il circuito non abbia uno spazio target specifico. Quindi puoi semplicemente collegarlo al file XML e lo convaliderà. Questo viene fatto quasi allo stesso modo, solo che non puoi dichiarare affatto gli spazi nel file XML, ma semplicemente connettere lo schema.
<?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>
Come puoi vedere, questo viene fatto utilizzando noNamespaceSchemaLocation e specificando il percorso dello schema. Anche se lo schema non dispone di uno spazio di destinazione, il documento verrà convalidato. E il tocco finale: possiamo importare altri diagrammi in diagrammi e quindi utilizzare elementi di un diagramma in un altro. Pertanto, possiamo utilizzare in alcuni circuiti elementi che sono già in altri. Esempio:

Schema in cui viene dichiarato il tipo proprietario:

<?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>

Il secondo schema, che utilizza il tipo proprietario del primo schema:

<?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>
Il secondo schema utilizza la seguente costruzione:
<import namespace="bonus" schemaLocation="xsd2.xsd" />
Usandolo, abbiamo importato tipi ed elementi da uno schema all'altro nello spazio bonus. Pertanto, abbiamo accesso al tipo bonus:proprietario. E nella riga successiva lo abbiamo usato:
<element name="owner" type="bonus:owner" />
Inoltre un po' di attenzione alla seguente riga:
elementFormDefault="qualified"
Questo attributo è dichiarato nello schema e significa che nei file XML ogni elemento deve essere dichiarato preceduto da un prefisso esplicito. Se non è presente, dobbiamo solo dichiarare un elemento esterno con un prefisso e dobbiamo anche impostare i prefissi in tutti gli elementi all'interno, indicando chiaramente che stiamo utilizzando esattamente gli elementi di questo schema. Ed ecco, infatti, un esempio di file XML convalidato da uno schema che ha importato un altro schema:
<?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>
Nella riga:
<bonus:telephone>+38-094-521-77-35</bonus:telephone>
Dobbiamo dichiarare esplicitamente il namespace bonus, che punta allo spazio di destinazione del primo schema, poiché elementFormDefault è qualificato (seleziona), quindi tutti gli elementi devono indicare esplicitamente il loro spazio.

Fine dell'articolo

Il prossimo articolo sarà l'ultimo della serie e riguarderà già l'elaborazione di file XML utilizzando Java. Impareremo a ottenere informazioni in diversi modi e così via. Spero che questo articolo ti sia stato utile e, anche se ci sono degli errori da qualche parte, ti insegnerà qualcosa di utile e nuovo, o forse ti darà semplicemente l'opportunità di comprendere meglio i file XML. Per coloro che desiderano esplorare questo argomento in modo più dettagliato, ho deciso di mettere insieme una piccola serie di collegamenti:
  • XSD Simple Elements - partendo da questo articolo iniziate a leggere e andate avanti, tutte le informazioni sugli schemi sono raccolte lì e sono spiegate più o meno chiaramente, solo in inglese. Puoi usare un traduttore.

  • video sui namespace, è sempre utile ascoltare un altro punto di vista su qualcosa se il primo non è chiaro.

  • Namespace XML è un buon esempio dell'uso dei namespace ed è abbastanza completo.

  • Nozioni di base su XML - Spazi dei nomi - Un altro breve articolo sugli spazi dei nomi.

  • Anche The Basics of Using XML Schema to Define Elements è un riferimento estremamente utile sugli schemi, ma è necessario leggerlo lentamente e attentamente, approfondendo il materiale.

Questo è tutto certo, spero che se vuoi imparare qualcosa di più profondo da questo, i link ti aiuteranno. Ho esaminato personalmente tutte queste fonti, studiando tutto il materiale e, nel complesso, queste sono state le più utili tra tutte le fonti che ho consultato, poiché ciascuna di esse o ha migliorato la comprensione di ciò che avevo già letto da qualche altra parte, oppure lasciami imparare qualcosa di nuovo, ma molto è stato fatto solo durante la pratica. Quindi, per coloro che vogliono davvero capire tutto questo abbastanza bene, il mio consiglio è: studiare i namespace, poi come connettere facilmente gli schemi ai file XML, e poi come scrivere la struttura del documento negli schemi. E, soprattutto, pratica. Grazie a tutti per l'attenzione e buona fortuna con la programmazione :) Articolo precedente: [Concorso] Nozioni di base su XML per un programmatore Java - Parte 1 di 3 Articolo successivo: [Concorso] Nozioni di base su XML per un programmatore Java - Parte 3.1 di 3 - SAX
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION