Dom i Java
Her finner du et enkelt program som åpner en XML-fil og viser den fram på litt forskjellig måte.
Programmet består av 2 filer:
- mainFrame.java som inneholder den interessante koden
- aFileFilter.java som hjelper oss å åpne riktige filer
Skjermbildet er som følger:
I det venstre tekstfeltet vises elementene i xml-fila som rå text. Til høyre ligger et listefelt som lar oss åpne/lukke noder som tilsvarer treet. Under denne trestrukturen er et enkelt tekstfelt som viser innholdet teksten i den noden vi klikker på.
Når en fil åpnes skjer tre ting:
- Innholdet parses og det etableres et DOM-tre
- Tekstfeltet til venstre fylles. Se funksjonen: txtDisplay
- Trestrukturen til høyre fylles. Se funksjonen: showAll
Etablering av DOM-tre
Følgende kodebiter er involvert i etblering av DOM-treet:
// JAXP packages import javax.xml.parsers.*; import org.xml.sax.*; import org.xml.sax.helpers.*; import org.w3c.dom.*; ... // DOM-stuff DocumentBuilderFactory dbf=null; DocumentBuilder db = null; Document doc = null; static final String outputEncoding = "UTF-16"; ... // Create a DocumentBuilderFactory and configure it dbf = DocumentBuilderFactory.newInstance(); dbf.setValidating(false); dbf.setIgnoringComments(false); dbf.setIgnoringElementContentWhitespace(false); dbf.setCoalescing(false); // The opposite of creating entity ref nodes is expanding them inline dbf.setExpandEntityReferences(true); // Create a DocumentBuilder that satisfies the constraints // specified by the DocumentBuilderFactory try { db = dbf.newDocumentBuilder(); } catch (ParserConfigurationException pce) { System.err.println(pce); System.exit(1); } ... boolean buildDom(String filename) { doc = null; try { doc = db.parse(new File(filename)); } catch (SAXException se) { System.err.println(se.getMessage()); return false; } catch (IOException ioe) { System.err.println(ioe); return false; } return true; }
Fylling av tekstfeltet, txtDisplay()
Funksjonen txtDisplay er rekursiv og kalles som: txtDisplay(doc,""); der doc er rota i DOM-treet.
void txtDisplay(Node n,String indent) { String S=""; // display n by type (name) short nodetype=n.getNodeType(); switch (nodetype) { case Node.ELEMENT_NODE : S=((Element)n).getTagName(); NamedNodeMap a_list=n.getAttributes(); for(int ix=0;ix < a_list.getLength();ix++) S+=" "+((Attr)a_list.item(ix)).getNodeName()+"=" +((Attr)a_list.item(ix)).getNodeValue(); break; case Node.TEXT_NODE: case Node.CDATA_SECTION_NODE : S=((CharacterData)n).getData(); break; default:S=n.getNodeName(); } if(S.trim().length() > 0) displayText=displayText+"\n"+indent+S; // do children if any for (Node child = n.getFirstChild(); child != null; child = child.getNextSibling()) { txtDisplay(child,indent+" "); } // finnish element if(nodetype==Node.ELEMENT_NODE) displayText=displayText+"\n"+indent+ "end of: "+n.getNodeName(); }
Fylling av trestrukturen, showAll()
Dette er en litt mer involvert operasjon. Fylling av en trelistekontroller i Java kan gjøres ved å etablere en separat trestruktur som så kan settes som innhold i listekontrollen. Nøkkelen til å gjøre dette på en enkel måte er DefaultMutableTreeNode som er en generell nodetype som på vanlig måte har en forelder og et vilkårlig antall barn. Når vi har etblert et tre med rot d ved hjelp av DefaultMutableTreeNode, kan vi initiere kontrolleren med: jTree1 = new JTree(d);
I programmet er det funksjonen elementsInTree(d,doc); som med utgangspunkt i DOM-treet doc etablerer hjelpetreet d. Du vil også se av koden at det er benyttet en enkel klasse: class MyNodeWrapper som på en enkel måte representerer en DOM-node i hjelpetreet. Det er mange måter å gjøre dette på. Den løsningen som er valgt her er preget av en smule latskap, og det faktum at en Javaklasse ikke kan arve fra to foreldre..