• Nem Talált Eredményt

XML dokumentum kezelése DOM segítségével

In document Szoftverfejlesztés II. (Pldal 83-89)

6. XML dokumentumok feldolgozása, kezelése

6.2.2 XML dokumentum kezelése DOM segítségével

A DOM segítségével az XML dokumentumot egy faszerkezetben reprezen-táljuk, ahol minden egyes csomópont az XML egy összetevőjének felel meg. A két legagyakoribb csomópont az elem csomópont (element node) és a szöveges csomópont (text node). A DOM függvények lehetővé teszik csomópontok hoz-záadását, eltávolítását, a csomópontok tartalmának megváltoztatását és a hie-rarchia bejárását.

A DOM egy nyelvfüggetlen eszköz, ugyanis a különböző programozási nyelvekben ugyanúgy történik a használata. A DOM mechanizmusa az alábbi ábrán látható:

11. ábra: A DOM API

Itt is egy gyártó objektumot használunk, ez a DocumentBuilderFactory, amelynek feladata egy DocumentBuilder példány előállítása, ez fog létrehozni egy olyan Document objektumot, amely megfelel a DOM specifikációnak. A DocumentBuilder.newDocument metódus segítségével tudunk egy üres Document példányt létrehozni, de a parse metódussal lehetőség van egy létező XML alapján Document előállítá-sára is. A DOM API használatához szükséges osztályok és interfészek az org.w3c.dom és javax.xml.parsers csomagokban találhatóak. Nézzük mindezt a gyakorlatban.

A feldolgozás hasonlóan indul, mint a SAX esetén. Szükség van egy DocumentBuilderFactory-ra, amelynek segítségével majd előállítjuk a DocumentBuilder-ünket, ez pedig létrehozza a dokumentumfát (Document).

1 DocumentBuilderFactory

dbf=DocumentBuilderFactory.newInstance();

2 DocumentBuilder db=dbf.newDocumentBuilder();

3 Document doc=db.parse(new File("albumok.xml"));

Innentől kezdve már csak az a dolgunk, hogy feldolgozzuk a Document példányunkat. A DOM fát bejárni nem olyan egyszerű, mint a SAX-os megjelení-tés. A következő ábrán jól láthatóak a DOM elemek (Node) közötti viszonyok:

12. ábra: Az albumok.xml DOM fája a DOM kapcsolatokkal Kell írnunk egy olyan metódust a megjelenítéshez, amely végigmegy a DOM fa csomópontjain, és megjeleníti az elemek attribútumainak értékét, illet-ve az elemek értékét. A csomópontokért Javában a Node interfész felelős.

Számos csomópont típus van, és mindhez tartozik egy nodeName, nodeValue és attributes információ. Ezek a következőek lehetnek a csomópont típusától függően (csak a legfontosabbak vanna felsorolva):

Csomópont típusa nodeName nodeValue attributes ATTRIBUTE_NODE attribútum neve az attrib. értéke null

CDATA_SECTION_NODE #cdata-section a CDATA rész tartalma

null

COMMENT_NODE #comment a megjegyzés

tartalma

null

DOCUMENT_NODE #document null null

DOCUMENT_TYPE_NODE dokumentumtípus neve

null null

ELEMENT_NODE a címke neve null NamedNodeMap

ENTITY_NODE az entitás neve null null

NOTATION_NODE a jelölés neve null null

TEXT_NODE #text a text csomópont

tartalma

null

16. A legfontosabb DOM csomópontok

A Node interfész fontosabb metódusai:

 String getNodeName(): a nodeName értéket adja vissza

 String getNodeValue(): a nodeValue értéket adja vissza

 void setNodeValue(String nodeValue): a nodeValue ér-tékének beállítása

 short getNodeType(): a csomópont típusát azonosító short ér-ték (1-12)

 Node getParentNode(): a csomópont szülőjét adja vissza

 NodeList getChildNodes(): a csomópont gyermekeinek listája

 Node getFirstChild(): a csomópont első gyermeke

 Node getLastChild(): a csomópont utolsó gyermeke

 Node getNextSibling(): a csomópontot követő csomópontot adja vissza

 NamedNodeMap getAttributes(): a csomópont attribútumai-nak listája

 Node insertBefore(Node uj,Node e): az uj csomópontot szúrja be az e elé

 Node replaceChild(Node uj,Node cs): a cs csomópontot cseréli le az uj-ra

 Node removeChild(Node torlendo): törli a csomópontot

 Node appendChild(Node uj): az uj csomopontot rakja be az aktuális csomópont gyermek csomópontjai után

 boolean hasChildNodes(): true, ha van gyermek csomópontja A DOM fa bejárását a következő metódus végzi:

1 public static void printNode(Node n) {

2 System.out.println(n.getNodeName()+" : "+

n.getFirstChild().getNodeValue());

3 if (n.getNodeType()==Node.ELEMENT_NODE) { 4 NamedNodeMap attr=n.getAttributes();

5 for (int j=0;j<attr.getLength();j++) { 6 printNode(attr.item(j));

7 }

8 NodeList nodes = n.getChildNodes();

9 for (int i=0;i<nodes.getLength();i++){

10 if (nodes.item(i).getNodeType()==

Node.ELEMENT_NODE) {

11 printNode(nodes.item(i)); csomó-pont értékét. Itt figyelni kell arra (az ábrán is látszik), hogy az elemeknél az ér-ték egy Text csomóponton belül van, ezt a Text csomópontot kérjük le a getFirstChild metódussal, és ennek az értéke lesz az elem valódi szöveges tartalma.

Ha a csomópont elem, akkor lekérjük az attribútumait, és mindre meghív-juk a printNode metódust. Majd lekérjük az elem csomópont gyermek csomó-pontjait, és ha azok is elemek, akkor azokra is meghívjuk a printNode metó-dust. Így elérhető a DOM fa teljes bejárása, legalábbis az adott feladatra (albumok.xml) vonatkozóan. A printNode első hívása így fog kinézni:

printNode(doc.getFirstChild());

Amit eddig láttunk, azt sokkal könnyebben megoldhattuk volna SAX segít-ségével. A DOM nem is bejáráskor hasznos, hanem ha módosítani kell az XML tartalmat, új elemeket, attribútumokat hozzáadni, törölni vagy módosítani.

A következő feladat az, hogy az összes album árát rakjuk be az album elemhez attribútumként, majd töröljük az ar elemet. Vagyis egy attribútum létrehozását és egy elem törlését kell elvégezni. Továbbá minden album elem-hez hozzá kell adni egy „eladott” nevű elemet, amelyben egy 100-as érték lesz (a próba kedvéért).

1 public static void setNewAttrib(Document d) { 2 NodeList nodes=d.getElementsByTagName("album");

3 NodeList prices=d.getElementsByTagName("ar");

4 for (int i=0;i<nodes.getLength();i++) { 5 if (nodes.item(i) instanceof Element) {

14 for (int i=prices.getLength()-1;i>=0;i--) {

15 prices.item(i).getParentNode().removeChild(

prices.item(i));

16 } 17 }

A metódusnak egy Document példányt adunk át, amely lényegében az XML dokumentum gyökere. Ezt kell használnunk, ha adott nevű elemeket kell lekérni a dokumentumfából vagy új elemeket kell hozzáadni ahhoz. Lekérjük az album és az ar elemeket egy NodeList-be, majd végigmegyünk rajtuk egy for ciklussal, és az i-edik albumnak beállítunk egy ar attribútumot a megfele-lő árral. Majd a Document példány (d) segítségével létrehozunk egy eladott nevű elemet (e) és egy Text típusú csomópontot (t), amelyet hozzáfűzünk az e-hez, majd ezt adjuk hozzá az aktuális album elemhez.

Ezután töröljük az összes ar elemet. Azért kell a lista végéről indulni (i=prices.getLength()-1), mert csak így törli az összes elemet. Ugyanis ellenkező esetben egy elem törlésével az utána lévők „lejjebb” csúsznak, és így minden második albumból nem fogja törölni az ar elemet!

Már csak két dolog van hátra, hogy szinte mindent tudjunk a DOM-os XML kezeléssel kapcsolatban, egy hibakezelő hozzáadása és az érvényességellenőr-zés. A hibakezeléshez írnunk kell egy olyan osztályt (pl. DOMErrorHandler), amely megvalósítja az ErrorHandler (org.xml.sax.ErrorHandler) interfészt. Érdekesség, hogy ugyanarról az interfészről van szó, amelyet a SAX-os hibakezelésnél is használtunk. A DOM feldolgozásnak ugyan köze nincs a SAX-hoz, de a hibakezelés módja azonos, vagyis sok dolgunk nincsen, a korábbi hibakezelő metódusokat kell egy osztályba belerakni:

1 public class DOMErrorHandler implements ErrorHandler{

2 ...

3 }

A hibakeresés beállítása pedig így néz ki:

1 Writer logF=new FileWriter(new Fi-le("log.txt"),true);

2 PrintWriter logS=new PrintWriter(new PrintStream(System.out));

3 db.setErrorHandler(new DOMErrorHandler(logF));

A séma hozzáadása és az érvényességellenőrzés teljesen megegyezik a SAX-nál látottakkal:

1 ...

2 SchemaFactory sf=SchemaFactory.newInstance(

"http://www.w3.org/2001/XMLSchema");

3 dbf.setSchema(sf.newSchema(new Fi-le("albumok.xsd")));

4 DocumentBuilder db=dbf.newDocumentBuilder();

6.2.3 Az Extensible Stylesheet Language

In document Szoftverfejlesztés II. (Pldal 83-89)