# Menüeinträge aus XML erzeugen



## Shuk (10. Apr 2005)

Hallo an alle,

ich möchte gerne eine Menüstruktur erstellen und die einzelnen Menüpunkte aus einer XML-Datei lesen.
Ich bin nun soweit, dass mir der Inhalt des gesamten XML Dokumentes aufgelistet wird. Benutzt habe ich dazu die Methoden des SAX Parsers.

Meine XML-Datei gliedert sich folgendermaßen:

```
<gui>

    <menu>
		Menupunkt 1
		<menuItem>Untermenupunkt 1</menuItem>
		<menuItem>Untermenupunkt 2</menuItem>
		<menuItem>Untermenupunkt 3</menuItem>
		<menuItem>Untermenupunkt 4</menuItem>
    </menu>

    <menu>
		Menupunkt 2
		<menuItem>Untermenupunkt 1</menuItem>
		<menuItem>Untermenupunkt 2</menuItem>
		<menuItem>Untermenupunkt 3</menuItem>
		<menuItem>Untermenupunkt 4</menuItem>
    </menu>

...usw.

</gui>
```

Meine Ausgabe (wenn ich die Tags nicht ausgeben lasse), sieht dann so aus:

```
Menupunkt 1
Untermenupunkt 1
Untermenupunkt 2
Untermenupunkt 3
Untermenupunkt 4

Menupunkt 2
Untermenupunkt 1
Untermenupunkt 2
Untermenupunkt 3
Untermenupunkt 4

... usw.
```

Jetzt ist meine Frage, wie kann ich diese Daten am besten und leichtesten so strukturieren, dass ich für jeden Menupunkt ein Objekt bekomme und dieses Objekt wiederum auf seine Untermenpunkte in Form von verketteten Objekten verweist? Also wie ich eine verkettete Liste mache, ist mir schon klar, aber wie weise ich die Daten zu, wann er was macht? Hoffe ihr versteht was ich meine.

Wie mein Code aussieht, könnt ihr hier sehen, da hab ich mich dran orinentiert:
http://www.torsten-horn.de/techdocs/java-xml.htm#Programmierbeispiel-SAX-Echo

Am 1. SAX-Programmierbeispiel:
XML einlesen und Elemente, Attribute und Textinhalte ausgeben


Ok, hoffe ihr könnt mir da schnell weiterhelfen, wäre super!


Danke und Gruß
Shuk


----------



## Roar (10. Apr 2005)

schau mal hier: http://www.java-forum.org/de/viewtopic.php?t=9952
das beutzt zwar JDom und der source ist auch nicht aktuell aber vielleicht hilfts dir weiter, zumal jdom viel einfacherer zu benutzen ist als der sax parser


----------



## Shuk (10. Apr 2005)

Hi, danke für die schnelle Antwort.
Was du da gemacht hast, sieht mal wirklich gut aus!

So ganz nachvollziehen kann ich den ganzen Code aber noch nicht  :roll: 

Kann ich im XML-Code explizit angeben, was jetzt der Menupunkt ist und was die dazugehörigen Unterelemente sind?
Und der Name der Menupunkte ist ja da ein Attribut, kann ich da dann auch Menupunktnamen reinschreiben, die Leerzeichen enthalten?

Das wären so die Fragen, die sich mir stellen, bevor ich mich weiter in den Code reindenke. Kannst du mir ja sicher schnell beantworten   


Gruß
Shuk


----------



## Roar (10. Apr 2005)

jo kannst du...
der gröbste unterschied ist wohl, dass der source da mit  Actions (javax.swing) arbeitet (d.h. es passiert auch was wenn du die items anklickst ) darum sieht das etwas anders aus...


----------



## Shuk (10. Apr 2005)

Also mit den Actions ist schon gut, die brauch ich ja auch dann 

Hab jetzt mal den Code kopiert und wollte mal ausprobieren, hab da aber noch ein paar Fehler drin wie es aussieht.

1) Mit dieser Importanweisung hat er Probleme, was kann/muss ich da ändern?


```
import org.jdom.Element;
import org.jdom.Attribute;
```

2) Die Actionklassen, wie kann ich die denn alle in eine Datei schreiben? Oder muss da für jede Klasse wieder ne eigene Datei angelegt werden? So wie es da steht, geht es nicht...


```
package xmledit.gui.actions;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;


public class HelpAction extends AbstractAction {

   public HelpAction() {
      putValue(NAME, "Help");
   }

   public void actionPerformed(ActionEvent e) {
      System.out.println("help");
   }
}

public class ExitAction extends AbstractAction {

   public ExitAction() {
       putValue(NAME, "Exit");
       putValue(MNEMONIC_KEY, new Integer((int)'E'));
   }

   public void actionPerformed(ActionEvent e) {
      System.out.println("exit");
   }
}

public class AboutAction extends AbstractAction {

   public AboutAction() {
   }

   public void actionPerformed(ActionEvent e) {
      System.out.println("about");
   }
}
```


3) Dann hab ich noch ne Klasse mit der Mainmethode angelegt, da findet er aber die Funktion setJMenuBar() nicht:

```
public class XMLGui {

	public static void main(String[] args) {
		XMLMenuBar xmb = XMLMenuBar.load(getClass().getResource("MenuBar.xml"));
        setJMenuBar(xmb.createJMenuBar()); 
	}
}
```


Kannst du mir da bitte nochmal weiterhelfen?
Und wie genau kann ich dann da Untermenüs anlegen, den Post im Originalbeitrag verstehe ich irgendwie nicht.


Danke 
Shuk


----------



## Roar (10. Apr 2005)

zu 1. wie gesagt die klassen verwenden jdom, kansnt du hier runterladen: www.jdom.org

zu 2. nein die musst du alle in verschiedene dateien schreiben

3. :autsch: hörmal wenn du gar kein fenster hats, wo willst du dieie menüleiste hinsetzen?

untermenüs gehen so (steht doch auch im thread):


```
<menu name="File" mnemonic="F">
    <menu name="New">
          <action class="xmledit.gui.actions.NewAction"/>
     </menu>
     <separator/>
     <action class="xmledit.gui.actions.ExitAction"/>
</menu>
```


----------



## Shuk (10. Apr 2005)

hm, ok, noch ne dumme Frage 

wo muss ich die jdom Sachen hinkopieren? Gibts da nen Standardordner?


----------



## Roar (10. Apr 2005)

Anonymous hat gesagt.:
			
		

> wo muss ich die jdom Sachen hinkopieren? Gibts da nen Standardordner?



die frage gabs 1k mal such bitte im forum!


----------



## Shuk (11. Apr 2005)

Irgendwie finde ich nicht die Antwort, die ich suche. Vielleicht suche ich auch falsch, keine Ahnung. Kannst du es mir schnell beschreiben oder nen Link geben? Wäre echt nett!


----------



## Shuk (12. Apr 2005)

Ok, habs hinbekommen   
Melde mich dann wieder bei weiteren Fragen, hoffe ihr habt noch was Geduld  :roll: 

Auf jeden Fall schonmal vielen Dank!


----------



## Shuk (12. Apr 2005)

Hi,

also ich habe es jetzt soweit hinbekommen, dass mir Eclipse mal keine Fehler mehr anzeigt. Allerdings bekomme ich folgenden Fehler wenn ich das Programm starte:


```
Exception in thread "main" java.lang.NullPointerException
	at org.jdom.input.SAXBuilder.build(SAXBuilder.java:809)
	at gui_1.XMLMenuBar.load(XMLMenuBar.java:46)
	at gui_1.XMLGui.<init>(XMLGui.java:58)
	at gui_1.XMLGui.main(XMLGui.java:80)
```

Meine Main-Methode sieht so aus:


```
// MAIN
	public static void main(String[] args) throws Exception 
	{
		XMLGui myGUI = new XMLGui();
		
		// Fenstereigenschaften setzen:
		myGUI.setWindowProperties();
		
		// Menue anzeigen:
		myGUI.show();
	}
```

Und der Konstruktor so:


```
// Konstruktor
	public XMLGui() throws Exception
	{
		// Anwendungsname setzen
		super(lblAppName);
		
		// Set up the GUI.
	    desktop = new JDesktopPane(); //a specialized layered pane
	
	    //this.createFrame(); //create first "window"
	    this.setContentPane(desktop);
	    
	    XMLMenuBar xmb = XMLMenuBar.load(getClass().getResource("MenuBar.xml"));
        this.setJMenuBar(xmb.createJMenuBar()); 
	}
```

Die Datei MenuBar.xml ist auch vorhanden.

Die anderen Methoden habe ich sonst eigentlich übernommen...
Eine Idee was da falsch läuft?


Gruß
Shuk


----------



## Shuk (12. Apr 2005)

Also beim Debuggen tritt der Fehler in der folgenden Methode der Datei XMLMenuBar.java auf:


```
public static XMLMenuBar load(URL u) throws JDOMException, IOException {
      Document d = new SAXBuilder().build(u);
      Element root = d.getRootElement();
      if(!root.getName().equals("menubar"))
         throw new IllegalArgumentException("Document is not a menubar definition");
      XMLMenuBar mb = new XMLMenuBar();
        List menus = root.getChildren("menu");
        for(int i = 0; i<menus.size(); i++) {
           Element el = (Element) menus.get(i);
           mb.addMenu(XMLMenu.createXMLMenu(el));
      }
      return mb;
   }
```

Und zwar gleich in der ersten Zeile:


```
Document d = new SAXBuilder().build(u);
```


Wird da irgendwie der Pfad nicht richtig übergeben oder muss ich den anders setzen?
Bitte um Hilfe!


Gruß
Shuk


----------



## Roar (12. Apr 2005)

liegt die MenuBar.xml im selben verzeichnis wie die XMLGui.class ?


----------



## Shuk (12. Apr 2005)

hm, nicht direkt. Ich hab in Eclipse mein Projekt und in diesem Ordner liegt sie dann drin. Die Java-Dateien liegen dann nochmal in einem Unterordner /src/packagename/
Kann es daran liegen? Hab auch schonmal nen absoluten Pfad eingegeben, hat aber nicht gebracht.


----------



## Roar (12. Apr 2005)

ja dann musst du die xml auch in den richtigen pfad legen, oder den pfad im code anpassen


----------



## Shuk (12. Apr 2005)

hm, hab sie jetzt mal zu den .class Dateien kopiert. Jetzt kommt allerdings ne andere Fehlermeldung:


```
Exception in thread "main" org.jdom.input.JDOMParseException: Error on line 2 of document file:/E:/eclipse-workspace/gui/bin/gui_1/MenuBar.xml: The processing instruction target matching "[xX][mM][lL]" is not allowed.
	at org.jdom.input.SAXBuilder.build(SAXBuilder.java:465)
	at org.jdom.input.SAXBuilder.build(SAXBuilder.java:810)
	at gui_1.XMLMenuBar.load(XMLMenuBar.java:46)
	at gui_1.XMLGui.<init>(XMLGui.java:58)
	at gui_1.XMLGui.main(XMLGui.java:80)
Caused by: org.xml.sax.SAXParseException: The processing instruction target matching "[xX][mM][lL]" is not allowed.
	at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
	at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLScanner.scanPIData(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanPIData(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLScanner.scanPI(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDispatcher.dispatch(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
	at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
	at org.jdom.input.SAXBuilder.build(SAXBuilder.java:453)
	... 4 more
Caused by: org.xml.sax.SAXParseException: The processing instruction target matching "[xX][mM][lL]" is not allowed.
	at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
	at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLScanner.scanPIData(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanPIData(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLScanner.scanPI(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDispatcher.dispatch(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
	at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
	at org.jdom.input.SAXBuilder.build(SAXBuilder.java:453)
	at org.jdom.input.SAXBuilder.build(SAXBuilder.java:810)
	at gui_1.XMLMenuBar.load(XMLMenuBar.java:46)
	at gui_1.XMLGui.<init>(XMLGui.java:58)
	at gui_1.XMLGui.main(XMLGui.java:80)
```
Hast du da ne Idee zu der kleinen Fehlermeldung  :roll:


----------



## Roar (12. Apr 2005)

gib ma die xml


----------



## Shuk (12. Apr 2005)

```
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<menubar>
   <menu name="File" mnemonic="F">
      <menu name="New">
         <action class="xmledit.gui.actions.ExitAction"/>
      </menu>
      <separator/>
       <action class="xmledit.gui.actions.ExitAction"/>
   </menu>
   <menu name="Help" mnemonic="H">
       <action class="xmledit.gui.actions.HelpAction" enabled="false"/>
       <separator/>
       <action class="xmledit.gui.actions.AboutAction">
           <property key="Name" value="About"/>
       </action>
   </menu>
</menubar>
```

Hab ich eigentlich erstmal genau so übernommen...

Müssen bei diesen Angaben "<action class="xmledit.gui.actions.ExitAction"/> " irgndwelche Ordnerstrukuren so vorhanden sein?

Hast du von dem Teil vielleicht noch ne lauffähige Version, die du mir mal schicken könntest?


----------



## Roar (12. Apr 2005)

mach mal die leerzeile vor der pi weg.
das attribut class zeigt auf die entsprechende klasse, die mus snatürlich vorhanenden sein...


----------



## Shuk (12. Apr 2005)

ok, es geht wohl voran 
Jetzt ne andere Fehlermeldung:


```
Exception in thread "main" java.lang.ClassNotFoundException: xmledit.gui.actions.ExitAction
	at java.net.URLClassLoader$1.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at java.lang.ClassLoader.loadClassInternal(Unknown Source)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Unknown Source)
	at gui_1.XMLAction.createAction(XMLAction.java:68)
	at gui_1.XMLMenu.createJMenu(XMLMenu.java:86)
	at gui_1.XMLMenu.createJMenu(XMLMenu.java:83)
	at gui_1.XMLMenuBar.createJMenuBar(XMLMenuBar.java:70)
	at gui_1.XMLGui.<init>(XMLGui.java:59)
	at gui_1.XMLGui.main(XMLGui.java:80)
```

XML-Code sieht jetzt so aus:


```
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<menubar>
   <menu name="File" mnemonic="F">
      <menu name="New">
         <action class="xmledit.gui.actions.ExitAction"/>
      </menu>
      <separator/>
       <action class="xmledit.gui.actions.ExitAction"/>
   </menu>
   <menu name="Help" mnemonic="H">
       <action class="xmledit.gui.actions.HelpAction" enabled="false"/>
       <separator/>
       <action class="xmledit.gui.actions.AboutAction">
           <property key="Name" value="About"/>
       </action>
   </menu>
</menubar>
```

Anscheinend kommt er nicht mit dem xmledit... klar. Ich habe halt auch keine Ordner die so heißen, liegt da der Fehler? Wenn ja, wie müsste denn die Ordnerstruktur genau heißen wo dann welche Dateien liegen?

Nachtrag:

Liegt wirklich an den Actions, irgendwie hab ich da wohl keine passende Struktur. Hab die ganzen actions mal auskommentiert und jetzt geht es. Muss ich also die noch irgendwie anpassen, dann sollte es auch mit den Actions gehen.

Allerdings noch ne Frage:
Wenn ich jetzt Untermenüpunkte anlege, dann erscheint da immer noch so ein Pfeil rechts neben der Bezeichnung. Wie kriege ich den denn weg?


----------



## Roar (12. Apr 2005)

uff. du musst auch shcon die richite klasse angeben. die datei die ich gepostet hab war ein Beispiel!

bei untermenüpunkten ist rechts imemr ein pfeil. egal ob du die manuell anlegst und egal ob metal win oder sonstwas look and feel :-/


----------



## Shuk (14. Apr 2005)

Ok habs hinbekommen. Danke dir vielmals für deine Hilfe und Geduld!

Gruß
Shuk


----------

