Rad s XML-om u Groovyju

1. Uvod

Groovy nudi značajan broj metoda posvećenih prelaženju i manipulaciji XML sadržajem.

U ovom uputstvu pokazat ćemo kako dodavati, uređivati ​​ili brisati elemente iz XML-a u Groovyu koristeći razne pristupe. Pokazat ćemo i kako stvoriti XML strukturu od nule.

2. Definiranje modela

Definirajmo XML strukturu u našem direktoriju resursa koju ćemo koristiti u našim primjerima:

  Prvi koraci u Javi Siena Kerr 2018-12-01 Dockerizirajte svoju aplikaciju SpringBoot Jonas Lugo 2018-12-01 Vodič za SpringBoot Daniele Ferguson 2018-06-12 Java 12 uvida Siena Kerr 2018-07-22 

I pročitajte ga u InputStream varijabla:

def xmlFile = getClass (). getResourceAsStream ("articles.xml")

3. XmlParser

Počnimo istraživati ​​ovaj tok s XmlParser razred.

3.1. Čitanje

Čitanje i raščlanjivanje XML datoteke vjerojatno je najčešća XML operacija koju će programer morati obaviti. The XmlParser pruža vrlo jednostavno sučelje namijenjeno upravo tome:

def članci = novi XmlParser (). raščlanjivanje (xmlFile)

U ovom trenutku možemo pristupiti atributima i vrijednostima XML strukture pomoću izraza GPath.

Provedimo sada jednostavan test pomoću Spocka kako bismo provjerili je li naš članaka objekt je točan:

def "Treba li pravilno čitati XML datoteku" () {dato: "XML datoteku" kada: "Korištenje XmlParser za čitanje datoteke" def articles = novi XmlParser (). raščlaniti (xmlFile) onda: "Xml je pravilno učitan" članci. '* '.size () == 4 articles.article [0] .author.firstname.text () == "Siena" articles.article [2].' date-release'.text () == "2018-06- 12 "articles.article [3] .title.text () ==" Java 12 insights "articles.article.find {it.author. '@ Id'.text () ==" 3 "} .author.firstname. tekst () == "Daniele"}

Da bismo razumjeli kako pristupiti XML vrijednostima i kako koristiti izraze GPath, usredotočimo se na trenutak na unutarnju strukturu rezultata XmlParser # raščlanjivanje operacija.

The članaka objekt je instanca groovy.util.Node. Svaki Čvor sastoji se od imena, mape atributa, vrijednosti i roditelja (koji mogu biti bilo koji null ili drugi Čvor).

U našem slučaju vrijednost članaka je groovy.util.NodeList instance, koja je klasa omota za zbirku Čvors. The NodeList proširuje java.util.ArrayList klasa koja omogućuje izdvajanje elemenata indeksom. Da bi se dobila vrijednost niza a Čvor, koristimo groovy.util.Node # text ().

U gornjem primjeru uveli smo nekoliko izraza GPath:

  • članci.članak [0] .autor.imeno - dobiti ime autora za prvi članak - članci.članak [n] bi izravno pristupiti nth članak
  • ‘*' - dobiti popis članakDjeca - to je ekvivalent groovy.util.Node # children ()
  • autor.'@id ' - dobiti Autor elementi iskaznica atribut - autor.'@attributeName ' pristupa vrijednosti atributa imenom (ekvivalenti su: autor [‘@ id '] i [e-pošta zaštićena])

3.2. Dodavanje čvora

Slično prethodnom primjeru, pročitajmo prvo XML sadržaj u varijablu. To će nam omogućiti da definiramo novi čvor i dodamo ga na naš popis članaka pomoću groovy.util.Node # append.

Provedimo sada test koji dokazuje našu poantu:

def "Treba dodati čvor postojećem xml-u pomoću NodeBuilder-a" () {dato: "XML objekt" def articles = novi XmlParser (). parse (xmlFile) kada: "Dodavanje čvora u xml" def articleNode = new NodeBuilder (). article ( id: '5') {naslov ('Prelazak XML-a u malom') autor {ime ('Martin') prezime ('Schmidt')} 'datum izdanja' ('2019-05-18')} članci.append (articleNode), zatim: "Čvor se dodaje u xml ispravno" članke. '*'. size () == 5 articles.article [4] .title.text () == "Prelazak XML-a u malom"}

Kao što možemo vidjeti u gornjem primjeru, postupak je prilično jednostavan.

Primijetimo i da smo koristili groovy.util.NodeBuilder, što je dobra alternativa korištenju Čvor konstruktor za naš Čvor definicija.

3.3. Izmjena čvora

Također možemo mijenjati vrijednosti čvorova pomoću XmlParser. Da bismo to učinili, još jednom ćemo raščlaniti sadržaj XML datoteke. Dalje, možemo uređivati ​​čvor sadržaja mijenjajući vrijednost polje Čvor objekt.

Sjetimo se toga dok XmlParser koristi izraze GPath, uvijek dohvatimo instancu NodeList, pa da bismo modificirali prvi (i jedini) element, moramo mu pristupiti koristeći njegov indeks.

Provjerimo svoje pretpostavke pisanjem brzog testa:

def "Treba izmijeniti čvor" () {dato: "XML objekt" def articles = novi XmlParser (). raščlaniti (xmlFile) kada: "Mijenjanje vrijednosti jednog od čvorova" articles.article.each {it.'release-date '[0] .value = "2019-05-18"} onda: "XML je ažuriran" articles.article.findAll {it.'release-date'.text ()! = "2019-05-18"}. prazno je() }

U gornjem primjeru koristili smo i Groovy Collections API za prelazak preko NodeList.

3.4. Zamjena čvora

Dalje, pogledajmo kako zamijeniti cijeli čvor, umjesto da samo modificiramo jednu od njegovih vrijednosti.

Slično dodavanju novog elementa, koristit ćemo i NodeBuilder za Čvor definiciju, a zatim pomoću nje zamijenite jedan od postojećih čvorova u njoj groovy.util.Node # replaceNode:

def "Treba zamijeniti čvor" () {dato: "XML objekt" def articles = novi XmlParser (). raščlaniti (xmlFile) kada: "Dodavanje čvora u xml" def articleNode = novi NodeBuilder (). article (id: '5' ) {title ('Prelazak XML-a u malom') autor {ime ('Martin') prezime ('Schmidt')} 'datum izdanja' ('2019-05-18')} članci.article [0] .replaceNode (articleNode), zatim: "Čvor je u xml pravilno dodan" člancima. '*'. size () == 4 articles.article [0] .title.text () == "Prelazak XML-a u malom"}

3.5. Brisanje čvora

Brisanje čvora pomoću XmlParser prilično je zeznuto. iako Čvor razred pruža ukloniti (čvor dijete) metodu, u većini slučajeva ne bismo je koristili sami.

Umjesto toga, pokazat ćemo kako izbrisati čvor čija vrijednost ispunjava zadani uvjet.

Prema zadanim postavkama pristup ugniježđenim elementima pomoću lanca Node.NodeList reference vraća kopiju odgovarajućih podređenih čvorova. Zbog toga ne možemo koristiti java.util.NodeList # removeAll metoda izravno na našem članak kolekcija.

Da bismo predikatom izbrisali čvor, prvo moramo pronaći sve čvorove koji odgovaraju našem stanju, a zatim ih pregledati i pozvati java.util.Node # ukloni metoda na roditelju svaki put.

Primijenimo test koji uklanja sve članke čiji autor nema ID 3:

def "Treba ukloniti članak iz xml-a" () {dato: "XML objekt" def articles = novi XmlParser (). raščlaniti (xmlFile) kada: "Uklanjanje svih članaka osim onih s id == 3" articles.article .findAll { it.author. '@ id'.text ()! = "3"}. svaki {articles.remove (it)} zatim: "Ostao je još samo jedan članak" articles.children (). size () == 1 articles.article [0] .author. '@ id'.text () == "3"}

Kao što vidimo, kao rezultat naše operacije uklanjanja, dobili smo XML strukturu sa samo jednim člankom, a njezin je id 3.

4. XmlSlurper

Groovy također nudi još jedan tečaj posvećen radu s XML-om. U ovom ćemo odjeljku pokazati kako čitati i manipulirati XML strukturom pomoću XmlSlurper.

4.1. Čitanje

Kao u našim prethodnim primjerima, krenimo sa raščlanjivanjem XML strukture iz datoteke:

def "Treba pravilno čitati XML datoteku" () {dato: "XML datoteku" kada: "Korištenje XmlSlurper za čitanje datoteke" def articles = novi XmlSlurper (). raščlaniti (xmlFile) tada: "Xml je pravilno učitan" članci. '* '.size () == 4 articles.article [0] .author.firstname == "Siena" articles.article [2].' date-release '== "2018-06-12" articles.article [3] .title == "Članci o Java 12" članci.article.find {it.author.'@id '== "3"} .author.firstname == "Daniele"}

Kao što vidimo, sučelje je identično onome od XmlParser. Međutim, izlazna struktura koristi groovy.util.slurpersupport.GPathResult, koja je klasa omota za Čvor. GPathResult pruža pojednostavljene definicije metoda kao što su: jednako () i toString () zamotavanjem Tekst čvora # (). Kao rezultat toga, polja i parametre možemo čitati izravno koristeći samo njihova imena.

4.2. Dodavanje čvora

Dodavanje a Čvor je također vrlo sličan korištenju XmlParser. U ovom slučaju, međutim, groovy.util.slurpersupport.GPathResult # appendNode pruža metodu koja uzima primjerak java.lang.Object kao argument. Kao rezultat, možemo pojednostavniti novo Čvor definicije koje slijede istu konvenciju koju je uveo ČvorGraditelj:

def "Treba dodati čvor u postojeći xml" () {dato: "XML objekt" def articles = novi XmlSlurper (). raščlaniti (xmlFile) kada: "Dodavanje čvora u xml" članke.appendNode {članak (id: '5') {title ('Prelazak XML-a u malom') autor {ime ('Martin') prezime ('Schmidt')} 'datum izdanja' ('2019-05-18')}} članci = novi XmlSlurper (). parseText (XmlUtil.serialize (članci)), zatim: "Čvor se u xml pravilno dodaje" člancima. '*'. Size () == 5 articles.article [4] .title == "Prelazak XML-a u malom"}

U slučaju da trebamo izmijeniti strukturu našeg XML-a sa XmlSlurper, moramo reinicijalizirati svoje članaka objekt da biste vidjeli rezultate. To možemo postići kombinacijom groovy.util.XmlSlurper # parseText i groovy.xmlXmlUtil # serialize metode.

4.3. Izmjena čvora

Kao što smo već spomenuli, GPathResult uvodi pojednostavljeni pristup manipulaciji podacima. To je rečeno, za razliku od XmlSlurper, vrijednosti možemo izravno modificirati pomoću naziva čvora ili naziva parametra:

def "Treba izmijeniti čvor" () {dato: "XML objekt" def articles = novi XmlSlurper (). raščlaniti (xmlFile) kada: "Mijenjanje vrijednosti jednog od čvorova" articles.article.each {it.'release-date '= "2019-05-18"} onda: "XML je ažuriran" articles.article.findAll {it.'release-date'! = "2019-05-18"} .isEmpty ()}

Primijetimo da kada mijenjamo samo vrijednosti XML objekta, ne moramo ponovno raščlaniti cijelu strukturu.

4.4. Zamjena čvora

Sada prijeđimo na zamjenu cijelog čvora. Opet, GPathResult dolazi u pomoć. Čvor možemo jednostavno zamijeniti pomoću groovy.util.slurpersupport.NodeChild # replaceNode, koji se proteže GPathResult i slijedi istu konvenciju o korištenju Objekt vrijednosti kao argumenti:

def "Treba zamijeniti čvor" () {dato: "XML objekt" def articles = novi XmlSlurper (). raščlaniti (xmlFile) kada: "Zamjena čvora" articles.article [0] .replaceNode {članak (id: '5') {title ('Prelazak XML-a u malom') autor {ime ('Martin') prezime ('Schmidt')} 'datum izdanja' ('2019-05-18')}} članci = novi XmlSlurper (). parseText (XmlUtil.serialize (članci)), zatim: "Čvor je pravilno zamijenjen" članci. '*'. Size () == 4 articles.article [0] .title == "Prelazak XML-a u malom"}

Kao što je bio slučaj prilikom dodavanja čvora, mijenjamo strukturu XML-a, tako da ga moramo ponovno raščlaniti.

4.5. Brisanje čvora

Za uklanjanje čvora pomoću XmlSlurper, možemo ponovno koristiti groovy.util.slurpersupport.NodeChild # replaceNode metoda jednostavnim pružanjem prazne Čvor definicija:

def "Treba ukloniti članak iz xml-a" () {dato: "XML objekt" def articles = new XmlSlurper (). parse (xmlFile) when: "Uklanjanje svih članaka osim onih s id == 3" articles.article .findAll { it.author.'@id '! = "3"} .replaceNode {} članci = novi XmlSlurper (). parseText (XmlUtil.serialize (članci)) zatim: "Ostao je još samo jedan članak" articles.children (). size () == 1 articles.article [0] .author. '@ id' == "3"}

Opet, izmjena XML strukture zahtijeva ponovnu inicijalizaciju naše članaka objekt.

5. XmlParser nasuprot XmlSlurper

Kao što smo pokazali u našim primjerima, običaji XmlParser i XmlSlurper prilično su slični. S više i manje možemo postići iste rezultate. Međutim, neke razlike među njima mogu nagnuti vagu prema jednom ili drugom.

Kao prvo,XmlParser uvijek raščlanjuje cijeli dokument na DOM-ish strukturu. Zbog toga možemo istovremeno čitati i upisivati ​​u nju. Ne možemo isto s XmlSlurper dok ljenjivije procjenjuje staze. Kao rezultat, XmlParser može potrošiti više memorije.

S druge strane, XmlSlurper koristi jednostavnije definicije, što pojednostavljuje rad. Toga se također trebamo sjetiti bilo kakve strukturne promjene napravljene u XML-u XmlSlurper zahtijevaju ponovnu inicijalizaciju, što može imati neprihvatljiv uspjeh u slučaju da se izvrše mnoge promjene jedna za drugom.

Odluka o upotrebi alata treba biti pažljiva i u potpunosti ovisi o slučaju upotrebe.

6. MarkupBuilder

Osim čitanja i manipulacije XML stablom, Groovy također nudi alate za stvaranje XML dokumenta od nule. Stvorimo sada dokument koji se sastoji od prva dva članka iz našeg prvog primjera groovy.xml.MarkupBuilder:

def "Treba pravilno stvoriti XML" () {dato: "Strukture čvorova" kada: "Korištenje MarkupBuilderTest za stvaranje xml strukture" def writer = new StringWriter () new MarkupBuilder (Writer) .articles {article {title ('Prvi koraci u Javi ') autor (id:' 1 ') {ime (' Siena ') prezime (' Kerr ')}' datum izdanja '(' 01.12.2018. ')} članak {naslov (' Dockerizirajte svoju aplikaciju SpringBoot ') autor (id: '2') {ime ('Jonas') prezime ('Lugo')} 'datum izdavanja' ('01.12.2018.')}} zatim: "Xml je pravilno stvoren" XmlUtil.serialize ( writer.toString ()) == XmlUtil.serialize (xmlFile.text)}

U gornjem primjeru to možemo vidjeti MarkupBuilder koristi isti pristup za Čvor definicije s kojima smo se koristili NodeBuilder i GPathResult prethodno.

Za usporedbu rezultata iz MarkupBuilder s očekivanom XML strukturom koristili smo groovy.xml.XmlUtil # serialize metoda.

7. Zaključak

U ovom smo članku istražili više načina manipulacije XML strukturama pomoću Groovyja.

Pogledali smo primjere raščlanjivanja, dodavanja, uređivanja, zamjene i brisanja čvorova koristeći dvije klase koje je pružio Groovy: XmlParser i XmlSlurper. Također smo razgovarali o razlikama među njima i pokazali smo kako pomoću XML-a možemo graditi stablo ispočetka MarkupBuilder.

Kao i uvijek, cjeloviti kôd korišten u ovom članku dostupan je na GitHubu.


$config[zx-auto] not found$config[zx-overlay] not found