# SAX Parser implementieren



## m11 (25. Apr 2015)

Guten Abend,

ich muss einen SAX Parser implementieren, der alle XML Files mit folgendem Aufbau parsen kann:


```
<?xml version="1.0" encoding="UTF-8"?><blumen>
    <narzisse>
        <bluetezeit>2</bluetezeit>
        <farbe>weiss</farbe></narzisse>
    <rose>
        <preis>1</preis>
        <bluetezeit>3</bluetezeit>
        <farbe>rot</farbe></rose>
    <tulpe>
        <preis>1</preis>
        <bluetezeit>1</bluetezeit>
        <farbe>rot</farbe></tulpe></blumen>
```

Mein Parser sieht bisher so aus:


```
class BlumenHandler extends DefaultHandler {    
    private Blumenladen bl;
    private Blume blume;
    private String text;
    
    public Blumenladen getBlumenladen() {
        return bl;
    }
    
    public void startDocument() {
        bl = new Blumenladen();
    }
    
    public void startElement(String namespaceURI, String localName,
            String qName, Attributes atts) {
        
        if (qName.equals("narzisse")) 
            blume = new Narzisse();
            
        if (qName.equals("rose")) 
            blume = new Rose();
        
        if (qName.equals("tulpe"))
            blume = new Tulpe();
        
        
    }
    
    public void characters(char[] chs, int start, int length) {
          text = String.valueOf(chs, start, length);
    }
    
    public void EndElement(String namespaceURI, String localName, String qName) {
            
            if (qName.equals("bluetezeit"))
                blume.setBluetezeit(Integer.parseInt(text));
            
            if (qName.equals("farbe"))
                blume.setFarbe(Farbe.valueOf(text));
            
            if (qName.equals("preis"))
                    blume.setPreis(Double.parseDouble(text));
            
            if (qName.equals("narzisse") || qName.equals("rose") || qName.equals("tulpe"))
                bl.addBlume(blume);
                    
    }
}
```

Zugrunde liegen eine Klasse Blumenladen: 

```
public class Blumenladen implements Iterable<Blume> {


    //Liste, um alle vorhandenen Blumen im Laden zu speichern
    private LinkedList<Blume> blumenbestand;


    public Blumenladen(){
        blumenbestand = new LinkedList<Blume>();
    }


    //Methode um eine Blume dem Blumenbestand hinzuzufuegen
    public void addBlume(Blume b){
        blumenbestand.add(b);
    }


    //Methode, um eine Blume aus dem Blumenbestand zu loeschen
    public void removeBlume(Blume b){
        blumenbestand.remove(b);
    }




    @Override
    public String toString(){
        return blumenbestand.toString();
    }


    
@Override
public Iterator<Blume> iterator() {
        return blumenbestand.iterator();
    }
}
```

und eine abstrakte Klasse Blumen:


```
public abstract class Blume {


    public abstract void setPreis(double preis);
    public abstract void setFarbe(Farbe farbe);
    public abstract void setBluetezeit(int bluetezeit);
}
```

Die Klassen Narzisse, Tulpe und Rose erben von BLume und spezifizieren die Typen.

Des Weiteren gibt es für die Farbe der Blumen:

```
public enum Farbe {
    ROT,ORANGE,WEISS,GELB,ROSA
}
```

Ich hoffe das reicht zum Verständnis. 
Ziel ist es, die Blumen aus dem XML File auszulesen und in der LinkedList in zu speichern. Diese möchte ich dann später ausgeben können.


```
public class MeinSaxBlumenladen {


    public static void main(String [] args) throws Exception {
        
        //Eingabe des Pfads als Kommandozeilenargument                         
System.out.println("Bitte den Dateipfad angeben: ");
        Scanner sc = new Scanner(System.in);
        String eingabe = sc.nextLine();
        
        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser saxParser = factory.newSAXParser();
        BlumenHandler handler = new BlumenHandler();
        saxParser.parse(new File(eingabe), handler);
        Blumenladen blumenladen = handler.getBlumenladen();
    
        
    
        System.out.println(blumenladen.toString());
        
        }
    }
```


----------



## knilch (26. Apr 2015)

Hi,
In deiner Klasse: 

```
class BlumenHandler extends DefaultHandler {  
   public void EndElement(String namespaceURI, String localName, String qName) {
        ...;
    }
}
```
eine solche Methode gibt es in der DefaultHandler- Klasse nicht. https://docs.oracle.com/javase/7/docs/api/org/xml/sax/helpers/DefaultHandler.html
Wenn du statt dessen folgende Methode nimmst, dann sollte es gehen: 

```
public void endElement(String uri, String localName, String qName) {
      ...;
   }
```
Für die Farbe wirst du mit deiner Enum ein Fehler erhalten. Versuch es mal so:

```
public enum Farbe {
    ROT("rot"),
    ORANGE("orange"),
    WEISS("weiss"),
    GELB("gelb"),
    ROSA("rosa");

    private String text;

    Farbe(String text) {
        this.text = text;
    }

    public String getText() {
        return this.text;
    }

    public static Farbe fromString(String text) {
        if (text != null) {
            for (Farbe farbe : Farbe.values()) {
                if (text.equalsIgnoreCase(farbe.text)) {
                    return farbe;
                }
            }
        }
        return null;
    }
}
```
Dann im Code:

```
...
blume.setFarbe(Farbe.fromString(text));
...
```


----------



## m11 (27. Apr 2015)

Vielen Dank, läuft nun wunderbar!


----------

