XML-mel való együttműködés a Groovy-ban

1. Bemutatkozás

A Groovy jelentős számú módszert kínál az XML-tartalom bejárására és manipulálására.

Ebben az oktatóanyagban bemutatjuk, hogyan kell elemeket adhat hozzá, szerkesztheti vagy törölheti az XML-ből a Groovy-ban különféle megközelítések alkalmazásával. Megmutatjuk azt is, hogyan kell hozzon létre egy XML struktúrát a semmiből.

2. A modell meghatározása

Határozzunk meg egy XML struktúrát az erőforrás könyvtárunkban, amelyet a példáinkban használunk:

  Az első lépések a Java Siena Kerrben 2018-12-01 Dockerize a SpringBoot alkalmazásban Jonas Lugo 2018-12-01 SpringBoot bemutató Daniele Ferguson 2018-06-12 Java 12 betekintés Siena Kerr 2018-07-22 

És olvassa el egy InputStream változó:

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

3. XmlParser

Kezdjük felfedezni ezt a patakot a XmlParser osztály.

3.1. Olvasás

Az XML fájl olvasása és elemzése valószínűleg a leggyakoribb XML művelet, amelyet a fejlesztőnek el kell végeznie. A XmlParser egy nagyon egyszerű felületet biztosít, pontosan ezt jelenti:

def cikkek = új XmlParser (). elemzés (xmlFile)

Ezen a ponton GPath-kifejezések segítségével férhetünk hozzá az XML-struktúra attribútumaihoz és értékeihez.

Végezzünk el egy egyszerű tesztet a Spock segítségével annak ellenőrzésére, hogy a mi cikkeket az objektum helyes:

def "Ha az XML fájlt megfelelően el kell olvasni" () {adott: "XML fájl", amikor: "Az XmlParser használata a fájl olvasásához" def articles = new XmlParser (). parse (xmlFile) then: "Az Xml megfelelően van betöltve" cikkek. '* '.size () == 4 cikk. cikk [0] .author.firstname.text () == "Siena" cikkek. cikk [2].' release-date'.text () == "2018-06- 12 "articles.article [3] .title.text () ==" Java 12 insights "articles.article.find {it.author. '@ Id'.text () ==" 3 "} .author.firstname. szöveg () == "Daniele"}

Az XML-értékekhez való hozzáférés és a GPath-kifejezések használatának megértéséhez koncentráljunk egy pillanatra a XmlParser # elemzés művelet.

A cikkeket Az objektum a groovy.util.Node. Minden Csomópont névből, attribútumok térképből, értékből és szülőből áll (amelyek lehetnek akár nulla vagy egy másik Csomópont).

Esetünkben a cikkeket egy groovy.util.NodeList példány, amely egy burkoló osztály a Csomóponts. A NodeList kiterjeszti a java.util.ArrayList osztály, amely az elemek index szerinti kinyerését biztosítja. Az a karakterlánc értékének megszerzéséhez Csomópont, használunk groovy.util.Node # text ().

A fenti példában bemutattunk néhány GPath kifejezést:

  • cikkek.cikk [0] .szerző. keresztnév - szerezd meg a szerző keresztnevét az első cikkhez - cikkek.cikk [n] közvetlenül hozzáférne a nth cikk
  • ‘*' - kap egy listát cikkGyermekei - ez egyenértékű groovy.util.Node # gyermek ()
  • szerző.'@id ' - szerezd meg a szerző elemé id tulajdonság - szerző.'@attributeName ' az attribútum értékét a neve alapján éri el (az ekvivalensek: szerző [’@ id’] és [e-mail védett])

3.2. Csomópont hozzáadása

Az előző példához hasonlóan olvassuk el először az XML tartalmat változóba. Ez lehetővé teszi számunkra, hogy meghatározzunk egy új csomópontot, és a segítségével hozzáadjuk a cikklistánkhoz groovy.util.Node # függelék.

Vezessünk most egy tesztet, amely igazolja a mi álláspontunkat:

def "Csomópontot kell hozzáadni a meglévő xml-hez a NodeBuilder használatával" () {adott: "XML objektum" def cikkek = új XmlParser (). parse (xmlFile), amikor: "Csomópont hozzáadása az xml-hez" def articleNode = új NodeBuilder (). cikk ( id: '5') {title ('XML bejárása dióhéjban') szerző {utónév ('Martin') vezetéknév ('Schmidt')} 'release-date' ('2019-05-18')} cikkek.append (articleNode) majd: "A csomópont megfelelően hozzáadva az xml-hez". '*'. size () == 5 articles.article [4] .title.text () == "XML bejárása dióhéjban"}

Amint a fenti példában láthatjuk, a folyamat meglehetősen egyszerű.

Vegyük észre azt is, hogy használtuk groovy.util.NodeBuilder, ami szép alternatíva a Csomópont kivitelező a mi Csomópont meghatározás.

3.3. Csomópont módosítása

A csomópontok értékeit a XmlParser. Ehhez még egyszer elemezzük az XML fájl tartalmát. Ezután szerkeszthetjük a tartalomcsomópontot a érték mező Csomópont tárgy.

Emlékezzünk arra, míg XmlParser a GPath kifejezéseket használja, mindig lekérjük a NodeList, így az első (és egyetlen) elem módosításához hozzá kell férnünk az indexével.

Ellenőrizzük feltételezéseinket egy gyors teszt megírásával:

def "Módosítania kell a csomópontot" () {adott: "XML objektum" def cikkek = új XmlParser (). parse (xmlFile) amikor: "Az egyik csomópont értékének megváltoztatása" articles.article.each {it.'release-date '[0] .value = "2019-05-18"}, majd: "Az XML frissül" articles.article.findAll {it.'release-date'.text ()! = "2019-05-18"}. üres() }

A fenti példában a Groovy Collections API-t is használtuk a NodeList.

3.4. Csomópont cseréje

Ezután nézzük meg, hogyan lehet az egész csomópontot kicserélni ahelyett, hogy csak módosítanánk az egyik értékét.

Hasonlóan egy új elem hozzáadásához, a NodeBuilder a Csomópont definíciót, majd cserélje ki a benne lévő meglévő csomópontok egyikét groovy.util.Node # csereNode:

def "Cserélje a csomópontot" () {adott: "XML objektum" def cikkek = új XmlParser (). parse (xmlFile), amikor: "Csomópont hozzáadása az xml-hez" def articleNode = új NodeBuilder (). cikk (id: '5' ) {title ('XML bejárása dióhéjban') szerző {utónév ('Martin') vezetéknév ('Schmidt')} 'release-date' ('2019-05-18')} cikkek.cikk [0] .replaceNode (articleNode) majd: "A csomópont megfelelően hozzáadva az xml-hez". '*'. size () == 4 articles.article [0] .title.text () == "XML bejárása dióhéjban"}

3.5. Csomópont törlése

Csomópont törlése a XmlParser elég trükkös. Habár a Csomópont osztály biztosítja a eltávolítás (csomópont gyermek) módszer, a legtöbb esetben nem önmagában használnánk.

Ehelyett megmutatjuk, hogyan lehet törölni egy olyan csomópontot, amelynek értéke megfelel egy adott feltételnek.

Alapértelmezés szerint a beágyazott elemek elérése a Node.NodeList hivatkozások példányt ad vissza a megfelelő gyermekek csomópontjai közül. Emiatt nem használhatjuk a java.util.NodeList # removeAll módszer közvetlenül a mi cikk Gyűjtemény.

Csomópont predikátummal történő törléséhez először meg kell találnunk az összes feltételnek megfelelő csomópontot, majd iterálnunk kell rajtuk és meg kell hívnunk java.util.Node # eltávolítás módszer minden alkalommal a szülőn.

Vezessünk be egy tesztet, amely eltávolít minden olyan cikket, amelynek szerzőjének azonosítója nem 3:

def "El kell távolítania a cikket az xml-ből" () {adott: "XML-objektum" def articles = new XmlParser (). parse (xmlFile) when: "Az összes cikk eltávolítása, kivéve az id == 3" cikkeket.article .findAll { it.author. '@ id'.text ()! = "3"} .each {articles.remove (it)}, akkor: "Csak egy cikk maradt" cikkek.gyerekek (). size () == 1 articles.article [0] .author. '@ id'.text () == "3"}

Mint láthatjuk, eltávolítási műveletünk eredményeként kaptunk egy XML struktúrát, csak egyetlen cikkel, és az azonosítója az 3.

4. XmlSlurper

A Groovy egy másik osztályt is kínál, amely az XML használatával foglalkozik. Ebben a részben bemutatjuk, hogyan olvasható és kezelhető az XML struktúra a XmlSlurper.

4.1. Olvasás

Az előző példákhoz hasonlóan kezdjük az XML struktúra elemzésével egy fájlból:

def "Az XML-fájlt megfelelően kell olvasni" () {adott: "XML-fájl", amikor: "Az XmlSlurper használata a fájl olvasásához" def articles = new XmlSlurper (). parse (xmlFile) then: "Az Xml megfelelően van betöltve" cikkek. '* '.size () == 4 cikk.cikk [0] .author.firstname == "Siena" cikkek.artikkel [2].' release-date '== "2018-06-12" articles.article [3] .title == "Java 12 betekintés" articles.article.find {it.author.'@id '== "3"} .author.firstname == "Daniele"}

Mint láthatjuk, az interfész megegyezik a XmlParser. A kimeneti struktúra azonban a groovy.util.slurpersupport.GPathResult, amely egy burkoló osztály Csomópont. GPathResult olyan módszerek egyszerűsített meghatározását nyújtja, mint például: egyenlő () és toString () csomagolással Csomópont # szöveg (). Ennek eredményeként csak a nevüket használva olvashatjuk el a mezőket és a paramétereket.

4.2. Csomópont hozzáadása

Hozzáadva a Csomópont szintén nagyon hasonlít a használatra XmlParser. Ebben az esetben azonban groovy.util.slurpersupport.GPathResult # appendNode olyan módszert biztosít, amely példányt vesz fel java.lang.Tárgy érvként. Ennek eredményeként egyszerűsíthetjük az újat Csomópont meghatározása ugyanazon egyezményt követi CsomópontÉpítész:

def "Csomópontot kell hozzáadni a meglévő xml-hez" () {adott: "XML objektum" def cikkek = új XmlSlurper (). parse (xmlFile), amikor: "Csomópont hozzáadása xml-hez" articles.appendNode {Article (id: '5') {title ('XML bejárása dióhéjban') szerző {firstname ('Martin') vezetéknév ('Schmidt')} 'release-date' ('2019-05-18')}} cikkek = új XmlSlurper (). parseText (XmlUtil.serialize (articles)), majd: "A csomópont megfelelően van hozzáadva az xml-hez". '*'. Size () == 5 articles.article [4] .title == "XML bejárása dióhéjban"}

Abban az esetben, ha módosítanunk kell az XML struktúráját a XmlSlurper, újra kell inicializálnunk cikkeket objektumot az eredmények megtekintéséhez. Ezt elérhetjük a groovy.util.XmlSlurper # parseText és a groovy.xmlXmlUtil # serialize mód.

4.3. Csomópont módosítása

Mint korábban említettük, a GPathResult egyszerűsített megközelítést vezet be az adatkezeléshez. Ennek ellenére, ellentétben a XmlSlurper, az értékeket közvetlenül módosíthatjuk a csomópontnév vagy a paraméternév segítségével:

def "Ha módosítania kell a csomópontot" () {adott: "XML objektum" def cikkek = új XmlSlurper (). parse (xmlFile), amikor: "Az egyik csomópont értékének megváltoztatása" articles.article.each {it.'release-date '= "2019-05-18"} majd: "Az XML frissül" articles.article.findAll {it.'release-date'! = "2019-05-18"} .isEmpty ()}

Vegyük észre, hogy amikor csak az XML objektum értékeit módosítjuk, akkor nem kell újra elemeznünk az egész struktúrát.

4.4. Csomópont cseréje

Most térjünk át az egész csomópont cseréjére. Ismét a GPathResult megmentésre kerül. Könnyen kicserélhetjük a csomópontot a groovy.util.slurpersupport.NodeChild # csereNode, amely kiterjed GPathResult és követi a Tárgy értékek mint argumentumok:

def "Cserélje a csomópontot" () {adott: "XML objektum" def cikkek = új XmlSlurper (). parse (xmlFile) amikor: "Csomópont cseréje" articles.article [0] .replaceNode {Article (id: '5') {title ('XML bejárása dióhéjban') szerző {firstname ('Martin') vezetéknév ('Schmidt')} 'release-date' ('2019-05-18')}} cikk = új XmlSlurper (). parseText (XmlUtil.serialize (articles)), majd: "A csomópont helyesen lett kicserélve" cikkek. '*'. Size () == 4 cikk. Cikk [0] .title == "XML bejárása dióhéjban"}

Ahogy egy csomópont hozzáadásakor történt, az XML felépítését is módosítjuk, ezért újra elemeznünk kell.

4.5. Csomópont törlése

Csomópont eltávolítása a XmlSlurper, újra felhasználhatjuk a groovy.util.slurpersupport.NodeChild # csereNode módszer egyszerűen egy üres megadásával Csomópont meghatározás:

def "El kell távolítania a cikket az xml-ből" () {adott: "XML-objektum" def articles = new XmlSlurper (). parse (xmlFile) when: "Az összes cikk eltávolítása, kivéve az id == 3" cikkeket.article .findAll { it.author.'@id '! = "3"} .replaceNode {} articles = new XmlSlurper (). parseText (XmlUtil.serialize (articles)), majd: "Csak egy cikk maradt" articles.children (). méret () == 1 cikk. cikk [0] .author. '@ id' == "3"}

Az XML struktúra módosítása megint megköveteli a cikkeket tárgy.

5. XmlParser vs. XmlSlurper

Amint a példáinkban bemutattuk, a XmlParser és XmlSlurper elég hasonlóak. Nagyjából ugyanazokat az eredményeket érhetjük el mindkettővel. A köztük lévő bizonyos különbségek azonban a mérleget egyik vagy másik felé billenthetik.

Először is,XmlParser mindig az egész dokumentumot DOM-ish struktúrába elemzi. Emiatt egyszerre olvashatunk belőle és írhatunk bele. Nem tehetjük ugyanezt XmlSlurper mivel lustábban értékeli az ösvényeket. Ennek eredményeként XmlParser több memóriát fogyaszthat.

Másrészről, XmlSlurper egyszerűbb meghatározásokat használ, így egyszerűbb a munka. Erre is emlékeznünk kell az XML használatával végrehajtott bármilyen strukturális változás XmlSlurper újrakezdést igényelnek, ami elfogadhatatlan teljesítménysütést okozhat sok változtatás esetén egymás után.

A döntést arról, hogy melyik eszközt használja, körültekintően kell meghozni, és teljes mértékben a felhasználási esettől függ.

6. MarkupBuilder

Az XML fa olvasása és manipulálása mellett a Groovy szerszámokat is biztosít az XML dokumentumok létrehozásához a semmiből. Hozzunk létre most egy dokumentumot, amely az első példánk első két cikkéből áll groovy.xml.MarkupBuilder:

def "Megfelelően kell létrehozni az XML-t" () {adott: "Csomópont struktúrák", amikor: "A MarkupBuilderTest használata az xml struktúra létrehozásához" def író = új StringWriter () új MarkupBuilder (író). cikkek {cikk {cím ('Első lépések a Java-ban ') author (id:' 1 ') {keresztnév (' Siena ') vezetéknév (' Kerr ')}' release-date '(' 2018-12-01 ')} cikk {title (' Dockerize a SpringBoot alkalmazásod ') author (id: '2') {keresztnév ('Jonas') vezetéknév ('Lugo')} 'release-date' ('2018-12-01')}}, majd: "Az Xml megfelelően van létrehozva" XmlUtil.serialize ( író.toString ()) == XmlUtil.serialize (xmlFile.text)}

A fenti példában ezt láthatjuk MarkupBuilder ugyanazt a megközelítést használja a Csomópont definíciókat használtunk NodeBuilder és GPathResult korábban.

A kimenet összehasonlításához MarkupBuilder a várható XML struktúrával a groovy.xml.XmlUtil # serialize módszer.

7. Következtetés

Ebben a cikkben az XML struktúrák Groovy segítségével történő manipulálásának számos módját tártuk fel.

Megnéztük a csomópontok elemzésének, hozzáadásának, szerkesztésének, cseréjének és törlésének példáit a Groovy által biztosított két osztály felhasználásával: XmlParser és XmlSlurper. Megbeszéltük a különbségeket is közöttük, és megmutattuk, hogyan építhetnénk fel egy XML fát a semmiből MarkupBuilder.

Mint mindig, a cikkben használt teljes kód elérhető a GitHubon.