# Leeres Array beim Auslesen von XML-Datei



## Adhiambo (22. Jun 2016)

Hallo guten Morgen,

ich möchte aus dieser XML-Datei den Discount-Wert des entsprechenden condtions-Tags auslesen.
*Conditions.xml*

```
<?xml version="1.0" encoding="UTF-8"?>
<conditions>
  <condition name="Ohne Skonto">
    <discount>0.00</discount>
  </condition>
  <condition name="5 Tage">
    <discount>2</discount>
  </condition>
</conditions>
```

Dazu habe ich folgende Java-Klasse "ReadConditions.java"

```
package tld.software.calculator;

public class ReadConditions {
    private XMLConditonsCreator element;
    public static void main(String[] args) {
        XMLConditonsCreator element = new XMLConditonsCreator();
        System.out.println(element.readXml("Ohne Skonto"));
    }
}
```
und die beiden Klassen, die importiert werden:
*Constants.java:*

```
package tld.software.calculator;

public class Constants {
    public final static String ATTRIBUTE_NAME = "name";
    public final static String ELEMENT_CONDITIONS = "conditions";
    public final static String ELEMENT_CONDITION = "condition";;
    public final static String ELEMENT_DISCOUNT = "discount";
}
```
*XMLConditonsCreator.java:*

```
package tld.software.calculator;

import static tld.software.calculator.Constants.ATTRIBUTE_NAME;
import static tld.software.calculator.Constants.ELEMENT_CONDITIONS;
import static tld.software.calculator.Constants.ELEMENT_CONDITION;
import static tld.software.calculator.Constants.ELEMENT_DISCOUNT;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;

import org.jdom2.*;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.jdom2.xpath.XPathFactory;
import org.jdom2.xpath.XPathExpression;
import org.xml.sax.SAXException;

import javax.xml.xpath.XPathExpressionException;

public class XMLConditonsCreator {
    private static String conditionFile = System.getProperties().getProperty("user.home")
            +File.separator+PlatformDependence.offerValue("directory")+File.separator + "Conditions.xml";
    private static File xmlFile = new File(conditionFile);
    private Namespace ns = Namespace.getNamespace("http://local.software.tld/calculator");
    private SAXBuilder builder = new SAXBuilder();
    private Document jdomDoc;

    public XMLConditonsCreator() {
        super();
    }

    public List<String> readXml(String conditionName) {
        List<String> results  = new ArrayList<String>();
        List<Element> elements = getConditionsElements(conditionName);
        if (elements != null) {
            results.add(conditionName);
            for (Element element : elements) {
                results.add(element.getValue());
            }
        }
        return results;
    }

    private static List<Element> getRootElements() {
        SAXBuilder builder = null;
        Document jdomDoc = null;
        try {
            builder = new SAXBuilder();
            jdomDoc = builder.build(xmlFile);
        } catch (JDOMException | IOException ex) {
            System.err.println(ex);
        }
        if (builder != null && jdomDoc != null) {
            return jdomDoc.getRootElement().getChildren();
        } else {
            return null;
        }
    }

    private static List<Element> getConditionsElements(String conditionName) {
        List<Element> serviceList = getRootElements();
        if (serviceList != null) {
            for (Element element : serviceList) {
                try {
                    if (element.getAttribute("name").equals(conditionName)) {
                        return element.getChildren();
                    }
                } catch ( NullPointerException ex ) {
                    ex.printStackTrace();
                    System.out.println("getConditionsElements wirft diese Exception");
                }
            }
        }
        return null;
    }

    public List<String> ConditionList() {
        List<String> ConditionList = new ArrayList<>();
        try {
            if (new File(System.getProperties().getProperty("user.home")+
                    File.separator+PlatformDependence.offerValue("directory")+
                    File.separator+PlatformDependence.offerValue("setting")).exists()) {
                jdomDoc = builder.build(xmlFile);
            }
            XPathFactory xFactory = XPathFactory.instance();
            XPathExpression xpath = xFactory.compile("conditions/condition/@name");
            for (Object opject : xpath.evaluate(jdomDoc)) {
                ConditionList.add(((Attribute)opject).getValue());
            }
        } catch (JDOMException | IOException ex) {
            ex.printStackTrace();
        }
        return ConditionList;
    }
}
```

Mein Problem ist, dass diese Konstruktion ein leeres Array zurückliefert, obwohl ein Array mit einem Wert zurückkommen müsste.
Wenn ich die ReadConditions.java mit dem Debugger starte und den Breakpoint bei System.out.println setze, sehe ich dass alles fehlerfrei durchläuft. Nur der Rückgabewert in readXml(String conditionName) results liefert "size=0" und in der For-Schleife ist "elements: null". So wird der Hauptklasse ein leeres Array als Ergebnis übergeben.

Ich sehe im Moment nicht, wo mein Ansatzfehler ist. Vielleicht könnt ihr mich bei der Suche unterstützen?

Vielen Dank 
Adhiambo


----------



## Joose (22. Jun 2016)

Adhiambo hat gesagt.:


> Wenn ich die ReadConditions.java mit dem Debugger starte ......
> 
> Ich sehe im Moment nicht, wo mein Ansatzfehler ist. Vielleicht könnt ihr mich bei der Suche unterstützen?


Hast du auch schon mal weiter in den Code debuggt? Die Methode `getConditionsElements` dürfte ja anscheinend nicht die gesuchten Felder liefern. 
Schon mal kontrolliert was dort passiert?


----------



## Adhiambo (22. Jun 2016)

Joose hat gesagt.:


> Hast du auch schon mal weiter in den Code debuggt? Die Methode `getConditionsElements` dürfte ja anscheinend nicht die gesuchten Felder liefern.
> Schon mal kontrolliert was dort passiert?


Ja, aber offen gesagt, ich werde im Moment nicht schlau daraus.


----------



## Flown (22. Jun 2016)

Musst du das alles händisch parsen? Geht doch viel einfacher mit JAXB und ist weit nicht so fehleranfällig wie dein Murks:

```
import java.io.StringReader;
import java.util.List;

import javax.xml.bind.JAXB;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;

public class Test {
  public static void main(String... args) {
    String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" +
        "<conditions>\r\n" +
        "  <condition name=\"Ohne Skonto\">\r\n" +
        "    <discount>0.00</discount>\r\n" +
        "  </condition>\r\n" +
        "  <condition name=\"5 Tage\">\r\n" +
        "    <discount>2</discount>\r\n" +
        "  </condition>\r\n" +
        "</conditions>";
    System.out.println(JAXB.unmarshal(new StringReader(xml), Conditions.class));
  }
}

@XmlRootElement(name = "conditions")
@XmlAccessorType(XmlAccessType.NONE)
@XmlSeeAlso({ Condition.class })
class Conditions {
  @XmlElement(name = "condition")
  List<Condition> conditions;

  public List<Condition> getConditions() {
    return conditions;
  }

  public void setConditions(List<Condition> conditions) {
    this.conditions = conditions;
  }

  @Override
  public String toString() {
    return "Conditions [" + conditions + "]";
  }

}

@XmlAccessorType(XmlAccessType.NONE)
class Condition {
  @XmlAttribute(name = "name", required = true)
  private String name;
  @XmlElement(name = "discount")
  private double discount;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public double getDiscount() {
    return discount;
  }

  public void setDiscount(double discount) {
    this.discount = discount;
  }

  @Override
  public String toString() {
    return "Condition [name=" + name + ", discount=" + discount + "]";
  }

}
```


----------



## Adhiambo (22. Jun 2016)

.


----------

