Vajon hogyan kerül elő a Rómeó és Júlia az it-tanfolyam.hu szakmai blogban témaként? Hiszen mégiscsak egy Shakespeare színműről/tragédiáról van szó. Vajon mit programozhatunk Java nyelven ehhez kötődően épp Valentin-napon? Mindjárt kiderül.
Tegyünk fel egy kérdést és próbáljunk rá válaszolni! Vajon ki szereti jobban a másikat? Rómeó vagy Júlia?
Induljunk el az adatforrásból, amihez alkalmazkodnunk kell. A színmű angol nyelven publikusan elérhető XML formátumban: The Tragedy of Romeo and Juliet. Az XML fájlok könnyen feldolgozhatók Java nyelven. Részletek a fájlból (görgethető):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
<?xml version="1.0"?> <!--<!DOCTYPE PLAY SYSTEM "play.dtd">--> <ACT><TITLE>ACT I</TITLE> <!--1--> <SPEECH> <SPEAKER></SPEAKER> <LINE>Two households, both alike in dignity,</LINE> <LINE>In fair Verona, where we lay our scene,</LINE> <LINE>From ancient grudge break to new mutiny,</LINE> <LINE>Where civil blood makes civil hands unclean.</LINE> ... </SPEECH> <!--2--> <SPEECH> <SPEAKER>ROMEO</SPEAKER> <LINE>Is the day so young?</LINE> </SPEECH> <!--3--> <SPEECH> <SPEAKER>ROMEO</SPEAKER> <LINE>Stay, fellow; I can read.</LINE> <STAGEDIR>Reads</STAGEDIR> <LINE>'Signior Martino and his wife and daughters;</LINE> <LINE>County Anselme and his beauteous sisters; the lady</LINE> ... <LINE>assembly: whither should they come?</LINE> </SPEECH> <!--4--> <SPEECH> <SPEAKER>ROMEO</SPEAKER> <LINE><STAGEDIR>To JULIET</STAGEDIR> If I profane with my unworthiest hand</LINE> <LINE>This holy shrine, the gentle fine is this:</LINE> <LINE>My lips, two blushing pilgrims, ready stand</LINE> <LINE>To smooth that rough touch with a tender kiss.</LINE> </SPEECH> <!--5--> <STAGEDIR>Enter JULIET</STAGEDIR> </ACT> |
Az XML fájl felépítését tanulmányozva (1-5 alapján) megállapíthatóak az alábbiak:
- A színmű öt felvonásból áll, ezeket <ACT></ACT> csomópontok jelölik.
- Egy „adagnyi” beszédet a <SPEECH></SPEECH> csomópont fog össze.
- A csomópontban található, hogy ki beszél: ez a <SPEAKER></SPEAKER> elem. A mesélő, kar esetén ez az elem üres, és a null-t nem szabad feldolgozni.
- A csomópontban találhatók a szabadvers kimondott sorai: ezek a <LINE></LINE> elemek. Legalább egy sor minden beszédben van, és nem tudjuk előre a számukat.
- Nem következetes helyen a DOM-ban, többféleképpen beágyazva és önállóan is előfordulhatnak <STAGEDIR></STAGEDIR> elemek. Ezek a színmű Kosztolányi-féle magyar fordításában dőlt betűvel megjelenő – cselekvésre utaló – színpadi utasítások. Van köztük csók is, amit az XML-ből nem szabad feldolgozni, bár erősen ráutaló magatartás. 🙂
- Nem tudjuk előre, hogy hány csomópont található a fájlban.
A Java program készítése, tesztelése közben – mintegy mellékesen – megtudhatjuk, hogy Rómeó 612 sorban 24075 betűnyi, Júlia 544 sorban 21855 betűnyi szöveget mond. Persze nem mindet egymásnak mondják. Eközben vajon hányszor mondják ki a szeret, szeretem, szeretlek szavakat? A ragoktól, toldalékoktól, kis- és nagybetűket nem megkülönböztetve és attól is eltekintve, hogy éppen kinek/kiknek mondják amit éppen mondanak, egy becsléshez elegendő, ha a love szóra fókuszálunk (számíthatna a loving alak is).
Az alábbi Java forráskód betölti az XML fájlt a memóriába. Ezután kiválogatja a beszédeket. Ha a beszélő élő ember (szereplő), akkor érdekes, hogy mit/miket mond. Ha ROMEO vagy JULIET mondja az adott sort, akkor azt a program kiválogatja két generikus listába ( romeoLineList és julietLineList) beszédnyi adagokban. Ez nem szétválogatás programozási tétel, mert nem minden beszéd minden sora kerül valahová. A kivételkezelés nem kidolgozott.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
private static ArrayList<String> getLineList(final Node SPEECH) { ArrayList<String> lineList=new ArrayList<>(); NodeList nodeList=((Element)SPEECH).getElementsByTagName("LINE"); for(int i=0; i<nodeList.getLength(); i++) { String line= ((Element)nodeList.item(i)).getFirstChild().getNodeValue(); lineList.add(line); } return lineList; } public static void main(String[] args) { ArrayList<String> romeoLineList=new ArrayList<>(); ArrayList<String> julietLineList=new ArrayList<>(); try { NodeList speechList=DocumentBuilderFactory.newInstance(). newDocumentBuilder().parse(new File("./files/r_and_j.xml")). getDocumentElement().getElementsByTagName("SPEECH"); for(int i=0; i<speechList.getLength(); i++) { Node speech=speechList.item(i); Node speaker=((Element)speech).getElementsByTagName("SPEAKER"). item(0).getFirstChild(); if(speaker!=null) switch(speaker.getNodeValue()) { case "ROMEO": romeoLineList.addAll(getLineList(speech)); break; case "JULIET": julietLineList.addAll(getLineList(speech)); } } } catch(ParserConfigurationException | SAXException | IOException e) { e.printStackTrace(); } //... } |
Könnyen megkaphatjuk, hogy Rómeó hány darab olyan sort mond, amely tartalmazza a love szót. Például ennek a lambda kifejezésnek kiíratva az eredményét a konzolra:
1 2 3 |
romeoLineList.stream(). filter(f->f!=null).filter(f->f.toLowerCase().contains("love")). count(); |
Könnyen megkaphatjuk Rómeótól a 53 sornyi szöveget is így:
1 2 3 |
romeoLineList.stream(). filter(f->f!=null).filter(f->f.toLowerCase().contains("love")). forEach(line->System.out.println(line)); |
Íme Rómeó kiválogatott sorai (az 5. sorban kétszer is előfordul a love, de ez most nem számít):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
Out of her favour, where I am in love. Alas, that love, whose view is muffled still, Here's much to do with hate, but more with love. Why, then, O brawling love! O loving hate! This love feel I, that feel no love in this. Why, such is love's transgression. With more of thine: this love that thou hast shown Love is a smoke raised with the fume of sighs; Being purged, a fire sparkling in lovers' eyes; Being vex'd a sea nourish'd with lovers' tears: In sadness, cousin, I do love a woman. A right good mark-man! And she's fair I love. From love's weak childish bow she lives unharm'd. She hath forsworn to love, and in that vow widow of Vitravio; Signior Placentio and his lovely One fairer than my love! the all-seeing sun Under love's heavy burden do I sink. Is love a tender thing? it is too rough, Did my heart love till now? forswear it, sight! It is my lady, O, it is my love! O, that I were a glove upon that hand, Call me but love, and I'll be new baptized; With love's light wings did I o'er-perch these walls; For stony limits cannot hold love out, And what love can do that dares love attempt; And but thou love me, let them find me here: Than death prorogued, wanting of thy love. By love, who first did prompt me to inquire; If my heart's dear love-- The exchange of thy love's faithful vow for mine. Wouldst thou withdraw it? for what purpose, love? Love goes toward love, as schoolboys from But love from love, toward school with heavy looks. How silver-sweet sound lovers' tongues by night, Then plainly know my heart's dear love is set And bad'st me bury love. I pray thee, chide not; she whom I love now Doth grace for grace and love for love allow; A gentleman, nurse, that loves to hear himself talk, Then love-devouring death do what he dare; Tybalt, the reason that I have to love thee But love thee better than thou canst devise, Till thou shalt know the reason of my love: Wert thou as young as I, Juliet thy love, My conceal'd lady to our cancell'd love? No nightingale: look, love, what envious streaks That may convey my greetings, love, to thee. And trust me, love, in my eye so do you: Ah me! how sweet is love itself possess'd, When but love's shadows are so rich in joy! By heaven, I love thee better than myself; Call this a lightning? O my love! my wife! Here's to my love! |
Hasonlóan megkaphatjuk Júlia 38 kiválogatott sorát is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
My only love sprung from my only hate! Prodigious birth of love it is to me, That I must love a loathed enemy. Or, if thou wilt not, be but sworn my love, Dost thou love me? I know thou wilt say 'Ay,' Thou mayst prove false; at lovers' perjuries If thou dost love, pronounce it faithfully: My true love's passion: therefore pardon me, And not impute this yielding to light love, Lest that thy love prove likewise variable. This bud of love, by summer's ripening breath, My love as deep; the more I give to thee, I hear some noise within; dear love, adieu! If that thy bent of love be honourable, Remembering how I love thy company. O, she is lame! love's heralds should be thoughts, Therefore do nimble-pinion'd doves draw love, My words would bandy her to my sweet love, Sweet, sweet, sweet nurse, tell me, what says my love? 'Your love says, like an honest gentleman, But my true love is grown to such excess Spread thy close curtain, love-performing night, Lovers can see to do their amorous rites By their own beauties; or, if love be blind, With thy black mantle; till strange love, grown bold, Think true love acted simple modesty. That all the world will be in love with night O, I have bought the mansion of a love, My dear-loved cousin, and my dearer lord? Believe me, love, it was the nightingale. Art thou gone so? love, lord, ay, husband, friend! To wreak the love I bore my cousin But thankful even for hate, that is meant love. I will confess to you that I love him. To live an unstain'd wife to my sweet love. Love give me strength! and strength shall help afford. And gave him what becomed love I might, What's here? a cup, closed in my true love's hand? |
Próbáljunk válaszolni a fentiek alapján a feltett kérdésre! Következtethetünk arra, hogy Rómeó jobban szereti Júliát. Legalábbis többször említi. 53>38. Persze tudjuk, hogy mindez nem ilyen egyszerű. 🙂
A bejegyzéshez tartozó teljes forráskódot ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.
A feladat a Java SE szoftverfejlesztő tanfolyam szakmai moduljának 21-24. óra: Objektumorientált programozás 2. rész, 25-28. óra: Objektumorientált programozás 3. rész, valamint a Java EE szoftverfejlesztő tanfolyam szakmai moduljának 9-12. óra: XML feldolgozás alkalmaihoz kötődik.
Nagyon különböző megoldásokat készíthetünk és szerteágazóan gyakorolhatunk, ha:
- az XML fájlt kézzel mentjük a webről és utána a helyi fájlrendszerből dolgozzuk fel,
- az XML fájlt közvetlenül a webről, dinamikusan olvassuk,
- csak beépített XML-feldolgozást használunk,
- külső XML API-t használunk,
- DOM, SAX, XSL, van-e DTD,
- XPath kifejezésekkel adunk választ a kérdésre,
- a fenti didaktikusan egyszerű megoldás helyett haladóbb eszközöket (például: Stream API-t) használunk.
A Rómeó és Júlia felidézte gimis – jambikus pentameterről szóló – rémálmomat. 🙂 Túl azon, hogy szétgyakoroltam magamat a fájlfeldolgozós példákon. Feltöltöttem az ILIAS-ba. Kiderült, hogy Rómeó 5245 és Júlia 4797 szót mond.
Bár én már kissé idősebb vagyok Berci, de át tudom érezni az élményt. 🙂 Örülök, hogy motivált a feladat.
Átnéztem Berci megoldását. Átírva megkaptam, hogy Rómeónak 163 adagnyi beszéde van.
Amire rákérdeznék: a betűk számát összegezve 25299-et kaptam. Sándor írtad a cikkben, hogy Rómeó 24075 betűnyi szöveget mond. Mi lehet az eltérés oka?
Anikó: a forráskódod nélkül próbálom kitalálni az okot. A különbség 1224. Rómeó 612 sornyi szöveget mond. 612*2=1224. Én soronként kérdeztem le a hosszt és ezeket adattam össze. Arra gondoltam, hogy összefűzted egybe Rómeó összes szövegét, majd lekérdezted a keletkezett szöveg hosszát. Például a generikus lista és a
String
függvényeivel így:toString().length()
. Ekkor sortörések kerülnek az összefűzött szövegbe a sorok közé. Ez fehér szóközként\n
, aminek a hossza 2 és 612 db van belőle. Így kaptad a nagyobb eredményt Anikó?Igen, pontosan 🙂 köszönöm.
Erik kombinálta a Rómeó és Júliát a Címkefelhő generálásával. A színműben szereplő 23692 szóból generálta ezt a szófelhőt:
Csoportváltással megoldottam a tegnapi házi feladatot. Nem minden kapott szám pontos. Kb. 2% eltérés lett az összes betűhöz képest. Még keresem az okokat. Ez TOP 6 legtöbbet beszélő szereplő = 10000 betűnél többet beszélő szereplő:
OK Berci, megbeszéljük majd a jövő heti órán.