2007-06-20

5 perc Java: XML gyártás

Az XML egy igen népszerű és elterjedt szabvány manapság. Szinte minden modern nyelvhez tartozó környezet támogatja bizonyos szinten, nincs ez így a Javával sem. Rendkívül sok lehetőségünk van a kezeléséhez (SAX, JAXP, stb.), de erről máskor.
Lássuk hát, mi is a helyes módja XML létrehozásának. Az XML belső szerkezetéhez szükséges elemeket az org.w3c.xml névtér tartalmazza, de ezek szinte mind abstract classok, ezért szükség lesz implementált classokra is. Ők a javax.xml névtér alatt érhetőek el. Én most a DOM rendszert fogom bemutatni (régebben: org.jdom névtér), amely az egész XML-t a memóriában tartja objektumok formájában (de ez még pár MB-os XML-nél sem nagy probléma), így viszont majd kell egy kis trükk, hogy fileba sorosítsuk.
Ennyit az elméleti bevezetőről. Lássuk akkor mi minden kell!

import java.util.Calendar;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.transform.*;
import org.w3c.dom.*;
[...]
try {
Calendar cal = Calendar.getInstance(); // java.util.Calendar

DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
// létrehoztuk a dokumentumot
Document doc = docBuilder.newDocument();
// elhelyeztük a legfelső node-ot, a root node-ot.
Element root = doc.createElement("root");

for (int i = 0; i<12)
{
cal.set(cal.MONTH, i); // na kitudja, hogy miért a 0. az első hónap? :)
// sajnos nem tördel a Java, ezért nekünk kell trükközni
root.appendChild(doc.createTextNode("\n"));
// most pedig egy új Node-ot hozunk létre
Element month = doc.createElement("month");
// majd beállítjuk tulajdonságként a hónap nevét,
month.setAttribute("name", cal.getDisplayName(cal.MONTH, cal.LONG, Locale.getDefault()));
// s a hónap sorszámát, ami a ciklus indexe
month.setAttribute("number", Integer.toString(i));
// miután beállítittuk a Node minden tulajdonságát, felkell vennünk egy másikba:
root.appendChild(month);
}
// ez így van a root-tal is, őt is felkell venni a dokumentumba!
doc.appendChild(root);

// most pedig a varázslat: sorosítjuk egy stream kimenetre, most a konzolra:
TransformerFactory xformFactory = TransformerFactory.newInstance();
Transformer idTransform = xformFactory.newTransformer();
Source input = new DOMSource(doc);
Result output = new StreamResult(System.out);
idTransform.transform(input, output);
}
catch (Exception e)
{
e.printStackTrace();
}


Ennek a kicsi programnak a kimenete a következő lesz:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<root>
<month name="január" number="0"/>
<month name="február" number="1"/>
<month name="március" number="2"/>
<month name="április" number="3"/>
<month name="május" number="4"/>
<month name="június" number="5"/>
<month name="július" number="6"/>
<month name="augusztus" number="7"/>
<month name="szeptember" number="8"/>
<month name="október" number="9"/>
<month name="november" number="10"/>
<month name="december" number="11"/>
</root>

Bónusz: ha tényleg fileba akarjuk menteni, akkor:
File outfile = new File("c:\\proba.xml");
BufferedWriter out = new BufferedWriter(new FileWriter(outfile));
Result output = new StreamResult(out);
idTransform.transform(input, output);
out.close();

Akit érdekel a téma, itt még rengeteg példát találhat.