XML file als Tree in SWT darstellen

GRU_EGO

Grünschnabel
Hallo,

ich habe folgendes Problem. Ich habe eine XML - Datei, die ich gerne als Tree in SWT tree darstellen möchte, d.h. nach dem Öffnen der Datei soll die Struktur als Nodes feststehen. Ich habe in der XML Datei alle Referenzen mit JDOM und XPath aufgelöst, und bekomme auf der Kommandozeile die Ausgabe. Funktioniert einwandfrei.

Hier ein Beispiel der XML - Datei:
<root xmlns:xsi="http://www.w3.org/">
<Hosts name="HostName" code="404" server="/root/constanten[@name='SSL']"/>
....
<constanten name="SSL" wert="1" type="int"/>
.....

Wenn ich es auflöse mit JDOM und XPath (JAXEN, SAXBuilder), erhalte ich auf der Kommandozeile:

<Hosts>name: HostName code: 404 server: 1int </Hosts>

Alles wunderbar. Jetzt habe ich eine GUI in SWT erstellt, nur wie bekomme ich nach dem Öffnen der Datei diese Darstellung als Tree angezeigt?

Danke für die Hinweise!
Grüsse
---------
EDIT:
So sieht es aus:

Code:
SAXBuilder builder = new SAXBuilder();
      example = builder.build( new File("xml/example.xml"));
      exampleRoot = example.getRootElement();

for (Iterator i = exampleRoot.getChildren("Hosts").iterator(); i.hasNext();) {
     Element e = (Element) i.next();
     Element singleTag = getSingleElementbyXPath("/root/Hosts[@name='HostName']");

String server = singleTag.getAttributeValue("server");
Element flag = (Element) getSingleElementbyXPath(server);
String out = flag.getAttributeValue("wert")+flag.getAttributeValue("type");

System.out.println("using name" + e.getAttributeValue("name") + "server" + out);
}

So löse ich es auf, es klappt wunderbar. Jetzt habe ich einen Baum:

TreeItem treeItem = new TreeItem(wurzel, SWT.NONE);
treeItem.setText("Knoten");

---> ich möchte aber, dass bei setText eben die Ausgabe von String out (davor im Quellcode) erscheint, also die aufgelöste Referenz.
Wie mache ich es?
Danke und Grüsse
 
Hallo!

Schau mal hier:

Java:
/**
 *
 */
package de.tutorials;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilderFactory;

import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * @author Thomas.Darimont
 */
public class JFaceXMLTreeExample extends ApplicationWindow {

	public JFaceXMLTreeExample(Shell shell) {
		super(shell);
		setBlockOnOpen(true);
	}

	protected void configureShell(Shell shell) {
		super.configureShell(shell);
		shell.setText("JFaceXMLTreeExample");
		shell.setSize(640, 480);
	}

	protected Control createContents(Composite composite) {

		TreeViewer treeViewer = new TreeViewer(composite);
		treeViewer.setContentProvider(createTreeContentProvider());
		treeViewer.setLabelProvider(createLabelProvider());
		treeViewer
				.setInput(createLazyTreeModelFrom("E:/eclipse/3.3M4/eclipse/features/org.eclipse.jdt_3.3.0.v20061213-1300b-KeyqHt5t5-Z9PT8/feature.xml"));
		return composite;
	}

	private IBaseLabelProvider createLabelProvider() {
		return new LabelProvider() {
			public String getText(Object element) {
				Node node = (Node) element;
				if (null == node) {
					return super.getText(element);
				} else if (Node.TEXT_NODE == node.getNodeType()) {
					return node.getTextContent().trim();
				} else {
					StringBuilder elementRepresentation = new StringBuilder("<");
					elementRepresentation.append(node.getNodeName());
					NamedNodeMap attributes = node.getAttributes();

					if (null == attributes) {
						elementRepresentation.append("/>");
						return elementRepresentation.toString();
					}

					int attributeCount = attributes.getLength();
					for (int i = 0; i < attributeCount; i++) {
						Node attributeNode = attributes.item(i);
						elementRepresentation.append(" ");
						elementRepresentation.append(attributeNode
								.getNodeName());
						elementRepresentation.append("=\"");
						elementRepresentation.append(attributeNode
								.getNodeValue());
						elementRepresentation.append("\"");
					}
					elementRepresentation.append("/>");
					return elementRepresentation.toString();
				}
			}
		};
	}

	private IContentProvider createTreeContentProvider() {
		return new ITreeContentProvider() {
			public Object[] getChildren(Object parentElement) {
				NodeList nodeList = ((Node) parentElement).getChildNodes();
				int nodesCount = nodeList.getLength();
				List<Node> nodes = new ArrayList<Node>();
				for (int i = 0; i < nodesCount; i++) {
					Node currentNode = nodeList.item(i);
					if (null != currentNode
							&& Node.TEXT_NODE == currentNode.getNodeType()
							&& "".equals(currentNode.getNodeValue().trim())) {
						System.out.println("Skip empty textnode:"
								+ currentNode.getNodeName());
						continue;
					}
					nodes.add(currentNode);

				}
				return nodes.toArray();
			}

			public Object getParent(Object element) {
				return ((Node) element).getParentNode();
			}

			public boolean hasChildren(Object element) {
				return ((Node) element).hasChildNodes();
			}

			public Object[] getElements(Object inputElement) {
				return getChildren(inputElement);
			}

			public void dispose() {
				// noop
			}

			public void inputChanged(Viewer viewer, Object oldInput,
					Object newInput) {
				// noop
			}
		};
	}

	private Object createLazyTreeModelFrom(String xmlFilePath) {
		Node documentNode = null;
		try {
			documentNode = DocumentBuilderFactory.newInstance()
					.newDocumentBuilder().parse(new File(xmlFilePath));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return documentNode;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		JFaceXMLTreeExample jfaceXmlTreeExample = new JFaceXMLTreeExample(
				new Shell());
		jfaceXmlTreeExample.open();
	}
}

Mit einem XML Binding Framework wie JAXB (2.x) / Castor / XMLBeans wärs noch viel einfacher...

Gruß Tom
 

Anhänge

  • 27582attachment.jpg
    27582attachment.jpg
    93 KB · Aufrufe: 455
Danke für Deine Antwort! Bekomme leider eine Fehlermeldung wg. ProgressMonitor can not be resolved, obwohl ich die jars richtig unter build path (project-preferences) eingebunden habe (runtime.jar, jface.jar).

Geht es auch ohne jface, also nur mit SWT? Ich müsste nur wissen, wie ich aus dem obigen Code:
Code:
String out = flag.getAttributeValue("wert")+flag.getAttributeValue("type");
diesen String out (ist ja nur gültig innerhalb der Schleife) an treeItem.setText(out); binden kann, d.h. mit return?
Wie müsste ich meine Methode ändern, dass sie als Rückgabewert den String ausliefert aus der Schleife, den ich dann in einer anderen Klasse mit extends Basisklasse wieder an den Knoten binden kann?
Dann könnte ich nämlich ohne jface alle Knoten so auflösen.

Danke für die Hinweise!
Wie gesagt, ich habe referenzen, die ich nur mit XPath auflösen kann...

Grüsse
 
Hallo!

Um mit JFace arbeiten zu können, brauchst du die jars der folgenden Plugins:
Code:
org.eclipse.core.boot
org.eclipse.core.jobs
org.eclipse.core.runtime
org.eclipse.core.commands
org.eclipse.equinox.common
org.eclipse.jface
org.eclipse.swt.xxxx

Ansonsten wär's natürlich auch möglich das allein mit SWT zu bauen, dass ist aber viel mühsamer als die JFace Variante SWT ist seeeeehr lowlevel...

Gruß Tom
 
Hallo!

Um mit JFace arbeiten zu können, brauchst du die jars der folgenden Plugins:
Code:
org.eclipse.core.boot
org.eclipse.core.jobs
org.eclipse.core.runtime
org.eclipse.core.commands
org.eclipse.equinox.common
org.eclipse.jface
org.eclipse.swt.xxxx

Ansonsten wär's natürlich auch möglich das allein mit SWT zu bauen, dass ist aber viel mühsamer als die JFace Variante SWT ist seeeeehr lowlevel...

Gruß Tom

Danke, Tom! Werde die fehlenden nun nachinstallieren. Melde mich dann, wenn alles funktioniert.
Gerne würde ich noch wissen, wie ich generell einen String in einer Methode (siehe oben Quellcode mit String out = ...) aus einer anderen Klasse ansprechen kann, d.h. den Rückgabewert übernehmen kann (unabhängig jetzt von Tree/swt). Wie müsste ich die obige for-Schleife umbauen, damit ich dann den String von anderen Klasse ansprechen kann,. d.h. das Ergebnis geliefert wird?
Danke für die Hinweise! Haben mir bisher sehr geholfen :)
Grüsse und bis später!
 
So, habe es geschafft, jetzt den String out mit return zu erhalten (für die spätere Wiederverwendung). Allerdings erhalte ich nur den letzten Eintrag aus der for - Schleife:
Code:
	public static String out() {
		String out = null;

for (Iterator i = exampleRoot.getChildren("Hosts").iterator(); i.hasNext();) {
     Element e = (Element) i.next();
     Element singleTag = getSingleElementbyXPath("/root/Hosts[@name='HostName']");

String server = singleTag.getAttributeValue("server");
Element flag = (Element) getSingleElementbyXPath(server);
String out = flag.getAttributeValue("wert")+flag.getAttributeValue("type");

		catch (IOException e) {
			System.out.println(e);
			e.printStackTrace();
		}
		return out;
}

	public static void main(String[] args) throws NameNotFoundException {
		 System.out.println(out());
}
Allerdings erhalte ich nur den letzten Wert der for-Iteration. Wie kann ich auch die vorigen, d.h. sind ja ca. 20 hosts davor, auch mit übernehmen, und nicht nur den letzten? Es in ein Array wandeln? Falls ja, wie?
Ich habe es auch mit collection versucht, funktioniert einwandfrei, aber ist halt alles in einer Zeile, und nicht getrennt...

Falls dies funktionieren wollte, kann ich es ja direkt in SWT/oder JFace umsetzen..
Danke und Grüsse
 
Habe es jetzt mit SWT only versucht:

Code:
public static Collection<String> sammlung (Collection<String> out) {
try {
//rest wie im beispiel oben
SAXBuilder builder = new SAXBuilder();
      example = builder.build( new File("xml/example.xml"));
      exampleRoot = example.getRootElement();

for (Iterator i = exampleRoot.getChildren("Hosts").iterator(); i.hasNext();) {
     Element e = (Element) i.next();
     Element singleTag = getSingleElementbyXPath("/root/Hosts[@name='HostName']");

String server = singleTag.getAttributeValue("server");
Element flag = (Element) getSingleElementbyXPath(server);
 out.add( flag.getAttributeValue("wert")+flag.getAttributeValue("type"));
}
} 		catch (IOException e) {
			System.out.println(e);
			e.printStackTrace();
		}
return out;
}

public static void main(String[] args) throws NameNotFoundException {
		
		 new meineKlasse(); 
		  Collection sammlungt= new LinkedList();
		 fill(out);
//hier der Baum in SWT

                       Display display = new Display ();
			Shell shell = new Shell (display);
			shell.setLayout(new FillLayout());
final Tree baum = new Tree (shell, SWT.Traverse);

				 int count = out.size();
//sind zur Zeit 3 Elemente
				 
				 for (int i=0; i<count; i++) {
					 System.out.println("zählen" + i + out);
			
					 TreeItem iItem = new TreeItem (baum,count);
					 iItem.setText("zählen " + i+ out);
					 System.out.println(out);
				 }
			shell.setSize (200, 200);
			shell.open ();
			while (!shell.isDisposed()) {
				if (!display.readAndDispatch ()) display.sleep ();
			}
			display.dispose ();
		 
		 
	
		}
}

Mein Problem: size ist 3, da es ja 3 tags sind - erhalte also auf der Kommandozeile:
zähle0
zähle1
zähle2

in SWT im Baum genauso, also
----zähle0
----zähle1
----zähle2

aber es sollte dahinter mit out nur das erste element stehen, dann das zweite, das dritte:
also so
----zähle0 name1=....
----zähle1 name 2=...
----zähle2 name3 = ...

bei mir stehen aber alle dahinter, also:

----zähle0 name1=...name2=...name3=...
----zähle1 name1=... name2=...name3=...
----zähle2 name1=... name2= ...name3=...


wie kann es es nur mit der zugehörigen Position angeben? Bitte um Hilfe! DANKE
PS: Die Ausgabe von out ist eine collection, sieht so aus:

[name1=...,name2=...,name3=...] und hat mit size() dann halt 3 Elemente
 
Zurück