import javax.swing.*; import java.awt.event.*; import java.io.*; import javax.xml.stream.*; import java.awt.*; import java.util.*; import javax.xml.bind.*; import javax.naming.spi.*; import xmlclasses.*; // The bound XML classes used to turn XML elements into objects. /** * Example of StAX and JaXB use. * * Uses the following schema:

* * <xsi:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.geog.leeds.ac.uk" xmlns="http://www.geog.leeds.ac.uk" elementFormDefault="qualified">
* <xsi:element name="map">
* <xsi:complexType>
* <xsi:sequence>
* <xsi:element name="polygon" minOccurs="0" maxOccurs="unbounded">
* <xsi:complexType>
* <xsi:sequence>
* <xsi:element name="points" type="xsi:string"/>
* </xsi:sequence>
* <xsi:attribute name="id" type="xsi:ID"/>
* </xsi:complexType>
* </xsi:element>
* </xsi:sequence>
* </xsi:complexType>
* </xsi:element>
* </xsi:schema>
*
*

*

* This should be saved in an xsd file in the same directory as this file * and the following command run against it at the command line: *

*

* xjc -p xmlclasses filename.xsd *

*

* This should generate the following classes: *

*

* Map.java - The class representing the root element of the XML
* ObjectFactory.java - Class for generating new copies of the XML root and sub-elements
* package-info.java *

*

* Compile these (note they are in the xmlclasses package). This should also generate classes representing the sub-elements that * are classes within Map.java. Provided you have the XSD file in the same directory * as this XMLExamples.java file, the new files should be in a xmlclasses directory within the directory * this java file and the XSD file is in. * (NB: this can be any package name - we've just pick this here and used it throughout). *

*

* You should then be able to compile and run this XMLExamples.java file, and use it to read in * XML files like this: *

*

* <?xml version="1.0" encoding="UTF-8"?>
* <?xml-stylesheet type="text/xsl" href="map2.xsl" ?>
* <map xmlns="http://www.geog.leeds.ac.uk" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="www.geog.leeds.ac.uk map2.xsd">
* <polygon id="p1">
* <points>100,100 200,100 200,200 100,0 100,100 </points>
* </polygon>
* </map> *

* * * @author Andrew Evans * @version 1.0 */ public class XMLExamples extends JFrame implements ActionListener { private Polygon polygon = null; // Default polygon. private String id = null; private String saveStaxMenuItemText = "Save StaX"; // GUI Strings - normally from a properties file. private String loadStaxMenuItemText = "Load StaX"; private String saveJaxbMenuItemText = "Save JaxB"; private String loadJaxbMenuItemText = "Load JaxB"; private String newJaxbMenuItemText = "New JaxB"; private String staxMenuText = "StaX"; private String jaxbMenuText = "JabX"; private boolean loaded = false; private Panel panel = null; private Label label = null; /** * Sets up the GUI. */ public XMLExamples () { // General GUI. super("XMLExamples"); setSize(300,300); setLocation(200,200); panel = new Panel(); panel.setSize(400,400); getContentPane().add(panel, BorderLayout.CENTER); label = new Label(" "); getContentPane().add(label, BorderLayout.SOUTH); // Menus. MenuBar menuBar = new MenuBar(); //menuBar.setOpaque(false); Menu staxMenu = new Menu(staxMenuText); menuBar.add(staxMenu); MenuItem saveStaxMenuItem = new MenuItem(saveStaxMenuItemText); saveStaxMenuItem.addActionListener(this); staxMenu.add(saveStaxMenuItem); MenuItem loadStaxMenuItem = new MenuItem(loadStaxMenuItemText); loadStaxMenuItem.addActionListener(this); staxMenu.add(loadStaxMenuItem); Menu jaxbMenu = new Menu(jaxbMenuText); menuBar.add(jaxbMenu); MenuItem saveJaxbMenuItem = new MenuItem(saveJaxbMenuItemText); saveJaxbMenuItem.addActionListener(this); jaxbMenu.add(saveJaxbMenuItem); MenuItem loadJaxbMenuItem = new MenuItem(loadJaxbMenuItemText); loadJaxbMenuItem.addActionListener(this); jaxbMenu.add(loadJaxbMenuItem); MenuItem newJaxbMenuItem = new MenuItem(newJaxbMenuItemText); newJaxbMenuItem.addActionListener(this); jaxbMenu.add(newJaxbMenuItem); setMenuBar(menuBar); // Setup default polygon. int [] xs = {100,200,200,100,100}; int [] ys = {100,100,200,000,100}; polygon = new Polygon(xs,ys,xs.length); id = "p1"; setVisible(true); doLayout(); repaint(); } /** * Allows XMLExamples to be used as an ActionListener. * Rather poorly, uses text items passed into constructor to determine * method to call. Would be better using Actions. * @param e */ public void actionPerformed(ActionEvent e) { if (((MenuItem)e.getSource()).getLabel().equals(saveStaxMenuItemText)) { writeStaxXML(); return; } if (((MenuItem)e.getSource()).getLabel().equals(loadStaxMenuItemText)) { readStaxXML(); return; } if (((MenuItem)e.getSource()).getLabel().equals(saveJaxbMenuItemText)) { writeJaxbXML(); return; } if (((MenuItem)e.getSource()).getLabel().equals(loadJaxbMenuItemText)) { readJaxbXML(); return; } if (((MenuItem)e.getSource()).getLabel().equals(newJaxbMenuItemText)) { newJaxbXML(); return; } } /** * Reads XML using Stax. */ private void readStaxXML() { // Get inputStream for a file. File file = getFileFromUser("Open"); if (file == null) return; FileInputStream in = null; try { in = new FileInputStream(file); } catch (IOException ioe) { ioe.printStackTrace(); } // Get an XML reader. XMLInputFactory factory = XMLInputFactory.newInstance(); XMLStreamReader parser = null; try { parser = factory.createXMLStreamReader(in); } catch (XMLStreamException xmlse) { xmlse.printStackTrace(); } // Parse the file. int event = 0; try { while (true) { event = parser.next(); // Having read the next XML component, check we're not EOF. if (event == XMLStreamConstants.END_DOCUMENT) { break; } // If not, parse XML element. if (event == XMLStreamConstants.START_ELEMENT) { // In our case here, we're only interested in the Polygon and Points // components in the XML file. if (parser.getLocalName().equals("polygon")) { // Although we've only got one attribute, this // shows how to use the attribute count. int length = parser.getAttributeCount(); for (int i = 0; i < length; i++) { if (parser.getAttributeLocalName(i).equals("id")) { id = parser.getAttributeValue(i); label.setText("id = " + id); } } } else if (parser.getLocalName().equals("points")) { polygon = buildPolygon(parser.getElementText()); loaded = true; repaint(); } } // End processing element. } // End processing all elements. parser.close(); } catch (XMLStreamException xmlse) { xmlse.printStackTrace(); } } /** * Write XML files using Stax. **/ private void writeStaxXML() { // Get outputStream for a file. File file = getFileFromUser("Save"); if (file == null) return; FileOutputStream out = null; try { out = new FileOutputStream(file); } catch (IOException ioe) { ioe.printStackTrace(); } // Get an XML writer. XMLOutputFactory factory = XMLOutputFactory.newInstance(); //factory.setProperty("javax.xml.stream.isRepairingNamespaces",new Boolean(true)); XMLStreamWriter writer = null; // Setup XML writer. try { writer = factory.createXMLStreamWriter(out, "UTF-8"); //writer.setDefaultNamespace("http://www.geog.leeds.ac.uk"); } catch (XMLStreamException xmlse) { xmlse.printStackTrace(); } // Start writing. try { // XML header writer.writeStartDocument("UTF-8", "1.0"); writer.writeProcessingInstruction("xml-stylesheet", "type=\"text/xsl\" href=\"map3.xsl\" "); // Root element. writer.writeStartElement("map"); // writer.writeNamespace("", "http://www.geog.leeds.ac.uk"); writer.writeNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"); writer.writeAttribute("xsi:schemaLocation", "www.geog.leeds.ac.uk map3.xsd"); // Sub-element. writer.writeStartElement("polygon"); writer.writeAttribute("id", id); writer.writeStartElement("points"); // Sub-sub-element. String points = getPoints(polygon); writer.writeCharacters(points); writer.writeEndElement(); // Close elements. writer.writeEndElement(); writer.writeEndElement(); writer.writeEndDocument(); writer.flush(); writer.close(); } catch (XMLStreamException xmlse) { xmlse.printStackTrace(); } // Close file. try { out.close(); } catch (IOException ioe) { ioe.printStackTrace(); } } /** * Reads XML using JaxB. */ private void readJaxbXML () { // Get inputStream for a file. File file = getFileFromUser("Open"); if (file == null) return; FileInputStream in = null; try { in = new FileInputStream(file); } catch (IOException ioe) { ioe.printStackTrace(); } // Unmarshall XML to objects. try { JAXBContext jaxbContext = JAXBContext.newInstance("xmlclasses"); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); xmlclasses.Map map = null; // In the following, the unmarshaller will attempt to unmarshall to // the root element class. If it fails it generates a generic // JAXBElement class object that can be interogated. try { map = (xmlclasses.Map) unmarshaller.unmarshal(in); } catch (Exception ee) { JAXBElement jaxElement = (JAXBElement) unmarshaller.unmarshal(in); System.out.println("name = " + jaxElement.getName()); System.out.println("type = " + jaxElement.getDeclaredType()); } // Get sub-elements and use. // The getPolygon methods etc. are generated by the xjc tool that creates the // appropriate classes. // In the following 'poly' is the unmarshalled object and 'polygon' is a // standard java.awt.polygon for drawing on the screen built by our 'buildPolygon' method // in this class. java.util.List polygonList = map.getPolygon(); xmlclasses.Map.Polygon poly = (xmlclasses.Map.Polygon) polygonList.get(0); polygon = buildPolygon(poly.getPoints()); id = poly.getId(); label.setText("id = " + id); loaded = true; repaint(); } catch (JAXBException je) { System.out.println(je.getMessage()); je.printStackTrace(); } } /** * Writes XML using JaxB. */ private void writeJaxbXML () { // Get outputStream for a file. File file = getFileFromUser("Save"); if (file == null) return; FileOutputStream out = null; try { out = new FileOutputStream(file); } catch (IOException ioe) { ioe.printStackTrace(); } try { // Get a binding between XML and classes. JAXBContext jaxbContext = JAXBContext.newInstance("xmlclasses"); // Use ObjectFactory created as part of binding to build a new // object representing the root element of the XML. xmlclasses.ObjectFactory factory = new xmlclasses.ObjectFactory(); xmlclasses.Map map = (xmlclasses.Map) factory.createMap(); // Fill it with appropriate sub-element classes. xmlclasses.Map.Polygon poly = (xmlclasses.Map.Polygon) factory.createMapPolygon(); poly.setId(id); poly.setPoints(getPoints(polygon)); java.util.List polygonList = map.getPolygon(); polygonList.add(poly); // Marshall root element class to XML. Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, new Boolean(true)); marshaller.marshal(map, out); } catch (JAXBException e) { System.out.println(e.getMessage()); e.printStackTrace(); } } /** * Generates a completely new object from the XML Schema, rather than reading one from XML file elements. */ private void newJaxbXML() { // Get outputStream for a file. File file = getFileFromUser("Save"); if (file == null) return; FileOutputStream out = null; try { out = new FileOutputStream(file); } catch (IOException ioe) { ioe.printStackTrace(); } // Use the ObjectFactory created during binding to // Generate a copy of the root element class and sub-elements. // Fill them, combine them, and use them. Here we use them by // marshalling to a XML file. try { JAXBContext jaxbContext = JAXBContext.newInstance("xmlclasses"); xmlclasses.ObjectFactory factory = new xmlclasses.ObjectFactory(); // Create the root element. xmlclasses.Map map = (xmlclasses.Map) factory.createMap(); // Create and fill sub-elements. xmlclasses.Map.Polygon poly = (xmlclasses.Map.Polygon) factory.createMapPolygon(); poly.setId("pt2"); poly.setPoints("100,100 100,200 200,200 200,100"); // Add the sub-elements to the list of sub-elements in the root element. java.util.List polygonList = map.getPolygon(); polygonList.add(poly); // Use the new object. polygon = buildPolygon(poly.getPoints()); id = poly.getId(); label.setText("id = " + id); loaded = true; repaint(); // Write the new object as XML. Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.marshal(map, out); } catch (JAXBException e) { e.printStackTrace(); } } /** * Convenience method to get a file from a user. * @param title - for dialog. * @return File picked or null if cancelled. */ private File getFileFromUser (String title) { JFileChooser chooser = new JFileChooser(); int returnVal = chooser.showDialog(this, title); if (returnVal == JFileChooser.APPROVE_OPTION) { return chooser.getSelectedFile(); } else { return null; } } /** * Convenience method to take in XML points and convert them to a java.awt.Polygon. * Will parse points with space or comma delimiters. * @param points should be in the form "x,y x,y x,y x,y". */ public Polygon buildPolygon(String points) { StringTokenizer st = new StringTokenizer(points, " ,"); String tempStr = null; int counter = 0; int [] xs = new int[st.countTokens()/2]; int [] ys = new int[st.countTokens()/2]; while (st.hasMoreTokens()) { tempStr = st.nextToken(); xs[counter] = Integer.parseInt(tempStr); tempStr = st.nextToken(); ys[counter] = Integer.parseInt(tempStr); counter++; } return new Polygon(xs,ys,xs.length); } /** * Convenience method to return a String of points from a java.awt.Polygon. * @return points will be in the form "x,y x,y x,y x,y". */ private String getPoints(Polygon polygon) { int [] xs = polygon.xpoints; int [] ys = polygon.ypoints; String tempStr = ""; for (int i = 0; i < xs.length; i++) { tempStr = tempStr + xs[i] + "," + ys[i] + " "; } tempStr.trim(); return tempStr; } /** * If a polygon has been loaded into the system, paint it. * @param g */ public void paint (Graphics g) { if (loaded) { Graphics jg = panel.getGraphics(); jg.translate(50,0); jg.drawPolygon(polygon); } } /** * Just starts everything going. * @param args */ public static void main (String args[]) { new XMLExamples(); } }