# Wie komme ich an die Siblings über DOM?



## navino (23. Apr 2018)

Hallo,

ich versuche folgende Daten über DOM auszuwerten und komme nicht an die Werte für ZutatId.
Ich finde kein Beispiel für den Zugriff:


```
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<zutaten>
  <zutat>
    <id>1</id>
    <name>Zucker</name>
    <notice>eine lange Bemerkung</notice>
    <inhaltstoffe>
        <ZutatId>4</ZutatId>
        <ZutatId>99</ZutatId>
    </inhaltstoffe>
  </zutat>
 
  <zutat>
    <id>2</id>
    <name>Mehl</name>
    <notice>eine lange Bemerkung für Mehl</notice>
    <inhaltstoffe>
        <ZutatId>12</ZutatId>
        <ZutatId>6</ZutatId>
        <ZutatId>7</ZutatId>
        <ZutatId>8</ZutatId>
        <ZutatId>9</ZutatId>
    </inhaltstoffe>
  </zutat>
</zutaten>
```


----------



## olfibits (23. Apr 2018)

Hier mal ein Beispiel dazu, wo genau so etwas mit Child-Tags gemacht wird => https://javabeginners.de/XML/XML-Datei_lesen.php
Hoffe das hilft weiter.


----------



## navino (23. Apr 2018)

Das Beispiel ist mit JDom gemacht, das darf ich leider nicht benutzen


----------



## Flown (23. Apr 2018)

Was darfst du denn verwenden?


----------



## navino (23. Apr 2018)

Alles was im Java jdk erhalten ist.
Externe Bibliotheken sind nicht erlaubt.


----------



## Flown (24. Apr 2018)

https://docs.oracle.com/javase/tutorial/jaxp/dom/readingXML.html

Was ist dein use-case. Wie lautet denn die Aufgabe. Warscheinlich ist XPath auch eine Lösung.


----------



## navino (24. Apr 2018)

Auf der Seite bin ich schon gewesen, da steht leider nicht welches xml-File benutzt wird, und verstehen tu ich das ehrlich gesagt auch nicht.
Das Usecase ist die Entwicklung eines Rezeptmanagers mit Java-Bordmitteln ohne Datenbank.
Ich habe mich jetzt für xml und DOM entschieden, muss ja auxh irgendwie gehen.
Das xml-File oben kann ich soweit auch lesen und in Objekte umwandeln. Nur an die ZutatenID's komme ich nicht dran. Da fehlt mir einfach die Syntax


----------



## Flown (24. Apr 2018)

Du hast dein Document Objekt und darauf wendest du dann `document.getElementsByTagName("zutat")` an. Damit erhälst du dann eine NodeList über die dann iterieren kannst:

```
public class Test {
  public static void main(String... args) {
    new Test().foo();
  }

  String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
    "<zutaten>\n" +
    "  <zutat>\n" +
    "    <id>1</id>\n" +
    "    <name>Zucker</name>\n" +
    "    <notice>eine lange Bemerkung</notice>\n" +
    "    <inhaltstoffe>\n" +
    "        <ZutatId>4</ZutatId>\n" +
    "        <ZutatId>99</ZutatId>\n" +
    "    </inhaltstoffe>\n" +
    "  </zutat>\n" +
    " \n" +
    "  <zutat>\n" +
    "    <id>2</id>\n" +
    "    <name>Mehl</name>\n" +
    "    <notice>eine lange Bemerkung für Mehl</notice>\n" +
    "    <inhaltstoffe>\n" +
    "        <ZutatId>12</ZutatId>\n" +
    "        <ZutatId>6</ZutatId>\n" +
    "        <ZutatId>7</ZutatId>\n" +
    "        <ZutatId>8</ZutatId>\n" +
    "        <ZutatId>9</ZutatId>\n" +
    "    </inhaltstoffe>\n" +
    "  </zutat>\n" +
    "</zutaten>";

  private void foo() {
    try {
      DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
      DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
      Document document = documentBuilder.parse(new InputSource(new StringReader(xml)));
      NodeList ingredients = document.getElementsByTagName("zutat");
      for (int i = 0; i < ingredients.getLength(); i++) {
        Element ingredient = (Element) ingredients.item(i);
        int id = Integer.parseInt(ingredient.getElementsByTagName("id").item(0).getTextContent());
        System.out.println(id);
      }
    } catch (SAXException | IOException | ParserConfigurationException e) {
      e.printStackTrace();
    }
  }
}
```
Mal ein Code zum ausführen.


----------



## Flown (24. Apr 2018)

Oder eben mit XPath:

```
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xPath = xPathFactory.newXPath();
NodeList paths = (NodeList) xPath.evaluate("//zutat/id/text()", document, XPathConstants.NODESET);
for (int i = 0; i < paths.getLength(); i++) {
  System.out.println(Integer.parseInt(paths.item(i).getNodeValue()));
}
```


----------



## navino (24. Apr 2018)

An die ID komme ich so, das ist auch nicht mein Problem dafür habe ich beispiele gefunden.
Ich benötige die Zutaten-Ids jeder Zutat (ZutatId). Die kommt aber mehrmals vor.


----------



## Flown (24. Apr 2018)

In welcher Form benötigst du das Ergebnis. Alle ZustatenIds von einer Zutat?


----------



## navino (24. Apr 2018)

Ja genau, ich möchte mir alle in einer Liste packen.


----------



## Flown (24. Apr 2018)

Alle ZutatenIds von allen Zutaten, oder per Zutat.

PS: Anders gefragt, wie soll die Liste aussehen für dein Beispiel XML?


----------



## navino (24. Apr 2018)

Ich benötige die ZutatId jeweils zur Zutat. 
Danke schon einmal für die Unterstützung!!


----------



## Flown (24. Apr 2018)

Wäre wahrscheinlicher sauberer, wenn man JAXB oder so nehmen würde, aber per hand gehts nur so:

```
try {
  DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
  DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
  Document document = documentBuilder.parse(new InputSource(new StringReader(xml)));
  
  XPathFactory xPathFactory = XPathFactory.newInstance();
  XPath xPath = xPathFactory.newXPath();
  
  Map<Integer, List<Integer>> ingredientMapping = new HashMap<>();
  
  NodeList ingredients = (NodeList) xPath.evaluate("//zutat", document, XPathConstants.NODESET);
  for (int i = 0; i < ingredients.getLength(); i++) {
    Node ingredient = ingredients.item(i);
    int id = ((Number) xPath.evaluate("./id/text()", ingredient, XPathConstants.NUMBER)).intValue();
    NodeList ingredientsIds = (NodeList) xPath.evaluate(".//ZutatId/text()", ingredient, XPathConstants.NODESET);
    for (int j = 0; j < ingredientsIds.getLength(); j++) {
      Node ingredientId = ingredientsIds.item(j);
      ingredientMapping.computeIfAbsent(id, k -> new ArrayList<>()).add(Integer.parseInt(ingredientId.getNodeValue()));
    }
  }
  System.out.println(ingredientMapping);
} catch (SAXException | IOException | ParserConfigurationException | XPathExpressionException e) {
  e.printStackTrace();
}
}
```


----------



## navino (25. Apr 2018)

Hallo und Danke für das Beispiel, da wäre ich nie drauf gekommen.
Was besser ist ist mir hier egal, da ich die persitenz als xml vorgeben habe.
Normalerweise würde ich eine Datenbank nehmen !!

Danke für den Support !!!


----------

