# XML lesen, ändern und speichern



## Jango Azzameen (16. Jan 2009)

Hallo,

ich habe folgendes Problem:
Ich lese über den SWT TreeViewer in einem Plugin eine XML Datei aus und lasse diese als TreeViewer in einem View Anzeigen. Auf einem anderen View werden die Werte der letzten Tags als Gui angezeigt.
Jetzt soll es möglich sein die Werte in der GUI zu verändern und diese auch in der XML-Datei an der passenden stelle schreiben. Desweiteren möchte ich bei dem TreeView mit der rechten Maus auf einen Tag klicken und über ein Kontext Menü einen neuen Tag hinzufügen, einen Tag löschen oder umbenennen.

Ich habe schon überall etwas gesucht aber nichts passenden gefunden.


MFG Jango


----------



## Vayu (16. Jan 2009)

wo ist dein problem? Also was dabei kannst du nicht? Hast du schon einen Ansatz?

Ansonsten, wie liest du die XML datei aus, wie verarbeitest du sie?


----------



## Jango Azzameen (16. Jan 2009)

Hallo,

ich hatte die Variante mit dem rechtclick über das widget Menu auf den treeviewer versucht doch treeviewer besitzt nicht die Methode setMenu()

Das auslesen funktioniert soweit, nur für das speichern finde ich keinen wirklichen ansatz ohne das die XML-Datei vollkommen neue geschrieben wird.

Hier ist der Code:

XMLView zum erstellen des Views aus der XML-Datei

```
public class XMLView extends ViewPart {

   public TreeViewer treeviewer;
   public static String file = "D:/test.xml";
      
   public XMLView() {	   
 
   }
     
  
   public void createPartControl(Composite parent) {
	   
	   	 treeviewer = new TreeViewer(parent, SWT.SINGLE);
	   	 treeviewer.setContentProvider(new XMLTreeContentProvider());
	   	 treeviewer.setLabelProvider(new XMLListLabelProvider());
	   	 treeviewer.setInput(ReadXMLFile.readXML(file));
	   	 
	   	 getSite().setSelectionProvider(treeviewer); 
   }   
  
   public void setFocus() {
      }
   }
```

mfg Jango


----------



## Jango Azzameen (16. Jan 2009)

Aus irgendendeinem Grund kann ich die QUelltexte nur einzeln posten daher sry.

ReadXMLFile zum auslesen der XML

```
import java.io.File;

import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.*;


public class ReadXMLFile {
	
	private static Node documentNode = null;
	private static Document doc;
	
    public static Object readXML(String xmlFilePath) {
        try {
            documentNode = DocumentBuilderFactory.newInstance()
                    .newDocumentBuilder().parse(new File(xmlFilePath));
            doc = (Document) documentNode;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return documentNode;
    }
    
    public static String[] getElement(String TagNam, String SelTagName){
    	
    	String[] NodeValue = new String[2];
    	  
        try {    	  
        	  doc.getDocumentElement().normalize();
        	  
        	  NodeList list = doc.getElementsByTagName(SelTagName);

        	  for (int i = 0; i < list.getLength(); i++) {
        	      Node node1 = list.item(i);
    	    	  String prnt = ((Element) node1).getElementsByTagName(TagNam).item(0).getParentNode().getNodeName();
        	      if (node1.getNodeType() == Node.ELEMENT_NODE && prnt.equals(SelTagName)) {
        	          	    	  
        	    	  Element element = (Element) node1;
        	    	  NodeList firstNodeElementList = element.getElementsByTagName(TagNam);
        	    	  Element element1 = (Element) firstNodeElementList.item(0);
        	    	  NodeList firstNodeList = element1.getChildNodes();
        	    	  
        	    	  Node value = firstNodeElementList.item(0).getChildNodes().item(0);
        	    	  
        	    	  if(value != null){
            	    	  NodeValue[0] = ((Node) firstNodeList.item(0)).getNodeValue();    	    		      	    		  
        	    	  }
        	    	  else{
            	    	  NodeValue[0] = " ";
        	    	  }
        	    	  
        	    	  NodeValue[1] = prnt;
        	      }
        	      else{
        	    	  NodeValue[0] = " ";
        	    	  NodeValue[1] = " ";
        	      }
        	  }
        	      
          } catch (Exception e) {}
          
          return NodeValue;
    }
}
```


----------



## Jango Azzameen (16. Jan 2009)

```
public class ListenerView extends ViewPart implements ISelectionListener
{
public void createPartControl(Composite parent) {
	
	 tk = new FormToolkit(parent.getDisplay());
	
	 GridLayout layout = new GridLayout();

  	 layout.numColumns = 2;
  	 layout.marginHeight = 20; //abstand vom oberern Rand
  	 layout.marginWidth = 20;  //abstand vom linken Rand
  	 
  	 parent.setLayout(layout);
  	 
 	 Composite cmp = tk.createComposite(parent);
  	 cmp.setLayout(new GridLayout(2, false));
  	 GridData gdCmp = new GridData(SWT.FILL, SWT.FILL, false, false);
  	 gdCmp.horizontalSpan = 2;
  	 cmp.setLayoutData(gdCmp);
  	 
  	 createGUI(cmp);

  	 btsave = (Button) createCTR("Speichern", normal, false, 3, parent, null);

  	 getViewSite().getPage().addSelectionListener(this);
}

public void selectionChanged(IWorkbenchPart part, ISelection selection) {
	SelTag = selection.toString();
	SelTagName = SelTag.substring(SelTag.indexOf("[[")+2, SelTag.lastIndexOf(": null]]"));
	
	for(int i=0; i<req.length; i++){
		selectChoice(chl[i], ReadXMLFile.getElement(req[i], SelTagName)[0]);
	}

	txl[0].setText(ReadXMLFile.getElement("ReqOIBCC", SelTagName)[1]);
	for(int i=0; i<othxml.length; i++){
		setLblTx(txl[i+1], ReadXMLFile.getElement(othxml[i], SelTagName)[0]);
	}
}

public void setLblTx(Text tx, String str){
	tx.setText(str);	
}

public void selectChoice(Combo ch, String str){
    for(int i=0; i<ch.getItemCount(); i++){
    	if(ch.getItems()[i].equals(str)){
    		ch.select(i);
    	}
    }	
}

}
```


----------



## Vayu (16. Jan 2009)

also was das Menu für den TreeViewer angeht, das machst du so


```
private void createContextMenu() {
        // Create menu manager.
        MenuManager menuMgr = new MenuManager();
        menuMgr.setRemoveAllWhenShown(true);
        menuMgr.addMenuListener(new IMenuListener() {
            public void menuAboutToShow(IMenuManager mgr) {
                fillContextMenu(mgr);
            }
        });

        // Create menu.
        Menu menu = menuMgr.createContextMenu(m_viewer.getControl());
        m_viewer.getControl().setMenu(menu);

        // Register menu for extension.
        getSite().registerContextMenu(menuMgr, m_viewer);
    }

    private void fillContextMenu(IMenuManager mgr) {
        // Hier füge deine actions in den mgr
        mgr.add(new Action(){...});
        mgr.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
    }
```

die createContextMenu rufst du in deiner init methode auf.

Was das einfügen/abändern von values und knoten in der xml datei angeht, da bietet dir doch die org.w3c.dom.Node schon alle notwendigen Methoden.


----------



## Jango Azzameen (16. Jan 2009)

Danke! 
wie sage ich der action, das er an dieser Stelle einen neuen Knoten hinzufügen soll. Hab es mit treeviewer.add(); und appendchild versucht doch das funktionier nicht


```
mgr.add(new Action("test"){
    	   		public void run(){
    	   			Object obj = treeviewer.getSelection();
    	   			Node nodeparent = (Node) obj;
    	   			Node newChild = null;
    	   			newChild.setNodeValue("test");
    	   			nodeparent.appendChild(newChild);
    	   		}
    	   }
```

oder muss ich das in dem ContentProvider und LabelProvider machen und wenn ja wie?

mfg Jango[/code]


----------



## Vayu (16. Jan 2009)

naja du hast doch irgendein model im hintergrund, in deinem Fall wahrscheinlich n Document oder ne NodeList? Dein ContentProvider arbeitet ja wahrscheinlich auf diesem Model.

Also füge an gewünschter Stelle in deinem Document einen neuen node ein und refreshe den treeviewer


----------



## Jango Azzameen (16. Jan 2009)

Das ändert aber nur das Model was dahinter steht es soll ja die ganze XML Datei geändert werden und nicht nur das was zu sehen ist.

MFG Jango


----------



## Vayu (16. Jan 2009)

naja dann bau dir halt ne save methode, die dein Document wieder zurückspeichert


----------



## Jango Azzameen (16. Jan 2009)

Und eben das ist das Problem ich habe keinen Ansatz wie ich diese Save Methode realisieren soll.

mfg Jango


----------



## Vayu (16. Jan 2009)

edit:

so


```
// use specific Xerces class to write DOM-data to a file:
    XMLSerializer serializer = new XMLSerializer();
    serializer.setOutputCharStream(
      new java.io.FileWriter("order.xml"));
    serializer.serialize(document);
```

oder so


```
Document d = db.parse(document);

TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer();
t.transform(new DOMSource(d), <output>);
```


----------



## Jango Azzameen (16. Jan 2009)

was ist bei dir db?

mfg Jango


----------



## Vayu (16. Jan 2009)

der DocumentBuilder ... den hast du ja schon in deiner readMethode

aber probier mal das erste CodeSample aus. habs noch reineditiert


----------



## Jango Azzameen (16. Jan 2009)

der kennt XMLSerializer nicht kannst du mir nen link geben wo ich die entsprechende Klasse finde

mfg Jango


----------



## Vayu (16. Jan 2009)

das ist ne Klasse vom Xerces

org.apache.xml.serialize

wenn du keine extra lib willst, dann nimm die TransformerFactory


----------



## Jango Azzameen (16. Jan 2009)

das hilft mir irgendwie nicht weiter, ds Output muss vom Typ Result sein dort kann ich jedoch keinen Pfad angeben


----------



## Ebenius (16. Jan 2009)

StreamResult verwenden diesem einen und FileOutputStream übergeben.

Hilft das?


----------



## Jango Azzameen (16. Jan 2009)

Danke das hat geholfen!

Ich habe jedoch noch das Problem einen neuen Knoten über ein Kontextmenü hinzuzufügen.
So sieht meine aktuelle Funktion aus, sie befindet sich in der XMLView:


```
private void createContextMenu() {
       // Create menu manager.
       MenuManager menuMgr = new MenuManager();
       menuMgr.setRemoveAllWhenShown(true);
       menuMgr.addMenuListener(new IMenuListener() {
           public void menuAboutToShow(IMenuManager mgr) {
               fillContextMenu(mgr);
           }
       });

       // Create menu.
       Menu menu = menuMgr.createContextMenu(treeviewer.getControl());
       treeviewer.getControl().setMenu(menu);

       // Register menu for extension.
       getSite().registerContextMenu(menuMgr, treeviewer);
   }

       mgr.add(new Action("Hinzufügen"){
    	   		public void run(){
    	   			//TODO: Einfügen eines neuen Knoten an selectierter Stelle
    	   			treeviewer.refresh();
    	   		}
    	   }
       );
       
       mgr.add(new Action("Löschen"){
	   		public void run(){
	   			//TODO: Löschen eines Knoten an selectierter Stelle
	   			treeviewer.refresh();
	   			}
	   		}
       );
       
       mgr.add(new Action("Umbenennen"){
	   		public void run(){
	   			//TODO: Umbennen des Knoten an selectierter Stelle
	   			treeviewer.refresh();
	   			}
	   		}
      );
       mgr.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
   }
```

MFG Jango


----------



## Vayu (16. Jan 2009)

ehm ich möchte mich ja jetzt nicht zitieren, aber ich hab doch schon vorhin schon geschrieben, dass die Klasse Node, die du aus deinem Document rausholen kannst schon die notwendigen Methoden liefert, die neue knoten in dein Document einfügen können ...


----------



## Jango Azzameen (19. Jan 2009)

Hallo,
hab ich schon versucht und die funktion removeChild(Node oldChild) ausprobiert und anschließend refresh aufgerufen aber es hat nichts gebracht.

Als Test hatte ich das verwendet:


```
mgr.add(new Action("Löschen"){
    	   public void run(){
    		   treeviewer.remove(treeviewer.getSelection());
    		   treeviewer.refresh();
    	   		}
       		}
       );
```


----------



## Vayu (19. Jan 2009)

... weil du sie nicht aus dem model sondern nur aus dem tree gelöscht hast ... hast du das nicht gemacht, was wir dir oben erklärt haben?


----------



## Jango Azzameen (19. Jan 2009)

Ok, hinzufügen und löschen funktioniert doch das umbennen nicht da es keine Methode setNodeName gibt oder muss ich das anders realisieren?

mfg Jango


----------



## Vayu (19. Jan 2009)

naja ich würd mal davon ausgehen, dass du statt rename ein add & remove machen musst


----------

