Eine einfache DOM-Anwendung

(Auszug aus "XML in a Nutshell" von Elliotte Rusty Harold & W. Scott Means)

Das folgende Beispiel illustriert, wie Sie die Interfaces, die in diesem Abschnitt beschrieben wurden, in einem typischen kleinen Programm verwenden könnten. Diese Anwendung liest ein Dokument, das der Beispiel-DTD moebel.dtd aus der XML-Referenz entspricht. Anschließend lädt sie die im Dokument angegebene Teileliste und vergleicht diese mit den tatsächlich angegebenen Teilen.

/**
 * MoebelPruefer.java
 *
 * Beispiel einer DOM-Anwendung aus O'Reilly's "XML in a Nutshell"
 *
 */

// Wir benutzen den Xerces-Parser von der Apache Software Foundation.
import org.apache.xerces.parsers.*;
import org.apache.xerces.framework.*;

// Import der DOM- und SAX-Interfaces
import org.w3c.dom.*;
import org.xml.sax.*;

// Import einiger weiterer Java-Klassen
import java.io.*;
import java.util.*;

/**
 * Diese Klasse überprüft die Gültigkeit einer in einem XML-Dokument enthaltenen
 * Teileliste.
 * Das XML-Dokument repräsentiert ein Möbelstück. Das DOM-Modell wird benutzt, um
 * die tatsächliche Möbelbeschreibung zu analysieren und sie mit der
 * im Dokument enthaltenen Möbelteileliste zu vergleichen.
 */
public class MoebelPruefer {
  // statische Konstanten
  public static final String FURNITURE_NS =
      "http://namespaces.oreilly.com/furniture/";
  // enthält die tatsächlich vorhandene Teilezahl mit Teilenummern als Schlüssel
  HashMap m_hmTruePartsList = new HashMap(  );

  /**
   * Die Funktion main erlaubt den Aufruf dieser Klasse von der Kommandozeile.
   * Alle auf der Kommandozeile angegebenen Dokumente werden auf Gültigkeit überprüft.
   */
  public static void main(String[] args) {
    MoebelPruefer mp = new MoebelPruefer(  );

    try {
      for (int i = 0; i < args.length; i++) {
        mp.pruefeTeileListe(args[i]);
      }
    } catch (Exception e) {
      System.err.println(e);
    }
  }
/**
   * Diese Methode bekommt einen SYSTEM-Identifier eines XML-Dokuments (d.h. einen
   * Dateinamen) übergeben.
   * Das Dokument wird gelesen, und die tatsächlich vorhandenen Teile werden mit den
   * deklarierten Teilen verglichen.
   * Wenn Differenzen festgestellt werden, wird eine Warnung auf der
   * Standardfehlerausgabe generiert.
   */
  public void pruefeTeileListe(String strXMLSysID) throws IOException,
      SAXException
  {
    // Erzeuge einen neuen Parser
    DOMParser dp = new DOMParser(  );

    // Parse das Dokument, und hole das DOM-Interface Document
    dp.parse(strXMLSysID);
    Document doc = dp.getDocument(  );

    // Bestimme die tatsächlich vorhandenen Teile
    zaehleTeile(doc.getDocumentElement(  ), 1);

    // Vergleiche Sie mit den deklarierten Teilen
    vergleicheMitTeileListe(doc);
  }

  /**
   * Generiert die Liste tatsächlich vorhandener Teile durch Summieren
   * der Anzahl der gegebenen Teile.
   */
  private void teilGefunden(String strTeileNummer, int cAnzahl)
  {
    if (!m_hmEchteTeileListe.containsKey(strTeileNummer)) {
      // Dieses Teil wird zum ersten Mal gefunden
      m_hmEchteTeileListe.put(strTeileNummer, new Integer(cAnzahl));
    } else {
      // Erhöhung des Zählers
      Integer cUpdate = (Integer)m_hmEchteTeileListe.get(strTeileNummer);
      m_hmEchteTeileListe.put(strTeileNummer, new Integer(cUpdate.intValue(  ) +
 cAnzahl));
    }
  }

  /**
   * Zählt die verwendeten Teile in diesem und in allen darin enthaltenen Knoten.
   */
  private void zaehleTeile(Node nd, int cWiederholungen)
  {
    // Starte den lokalen Wiederholungszähler bei 1
    int cLokaleWiederholungen = 1;

    // Stelle sicher, dass dieses Element verarbeitet werden soll
    if (MOEBEL_NS.equals(nd.getNamespaceURI(  ))) {
      Node ndTemp;
if ((ndTemp = nd.getAttributes(  ).getNamedItem("repeat")) != null) {
        // Dieser Knoten spezifiziert einen Wiederholungszähler für seine Kinder.
        cLokaleWiederholungen = Integer.parseInt(ndTemp.getNodeValue(  ));
      }

      if ((ndTemp = nd.getAttributes(  ).getNamedItem("teilenummer")) != null) {
        // Starte den Zähler bei 1
        int cAnzahl = 1;
        String strTeileNummer = ndTemp.getNodeValue(  );

        if ((ndTemp = nd.getAttributes(  ).getNamedItem("anzahl")) != null) {
          // Dieser Knoten benötigt mehr als ein Teil
          cAnzahl = Integer.parseInt(ndTemp.getNodeValue(  ));
        }

        // Multipliziere die lokale Anzahl mit dem Wiederholungszähler des
 Elternknotens
        cAnzahl *= cWiederholungen;

        // Addiere die Anzahl der neuen Teile zu der Summe
        teilGefunden(strTeileNummer, cAnzahl);
      }
    }

    // Nun werden die Kindknoten bearbeitet.
    NodeList nl = nd.getChildNodes(  );
    Node ndCur;

    for (int i = 0; i < nl.getLength(  ); i++) {
      ndCur = nl.item(i);

      if (ndCur.getNodeType(  ) == Node.ELEMENT_NODE) {
        // Rekursiver Aufruf, um die Teile im Kindknoten zu zählen
        zaehleTeile(ndCur, cLokaleWiederholungen);
      }
    }
  }

  /**
   * Diese Methode vergleicht die deklarierten Teilelisten mit den tatsächlich
   * vorhandenen.
   */
  private void vergleicheMitTeileListe(Document doc)
  {
    Iterator iReal = m_hmTruePartsList.keySet().iterator(  );

    String strTeileNummer;
    int cEchteAnzahl;
    Node ndVergleich;

    // Schleife über alle tatsächlich gefundenen Teile
    while (iReal.hasNext(  )) {
strPartNum = (String)iReal.next(  );
      cReal = ((Integer)m_hmEchteTeileListe.get(strTeileNummer)).intValue(  );

      // Finde das Element mit der Deklaration dieses Teils im Dokument
      ndCheck = doc.getElementById(strTeileNummer);

      if (ndVergleich == null) {
        // Dieses Teil ist nicht vorhanden!
        System.err.println("Unbekanntes <teil> mit TeileNummer #" +
            strTeileNummer + " (Anzahl " + cEchteAnzahl + ")");
      } else {
        Node ndTemp;

        if ((ndTemp = ndCheck.getAttributes(  ).getNamedItem("count")) != null) {
          int cVergleich = Integer.parseInt(ndTemp.getNodeValue(  ));

          if (cVergleich != cEchteAnzahl) {
            // Die Zähler stimmen nicht überein
            System.err.println(" Das <teil> mit der Teilenummer #" +
                strTeileNummer + " ist nicht korrekt:  Die echte Anzahl ist = " +
                cEchteAnzahl +
                " (der Zähler im Dokument ist " + cVergleich + ")");
          }
        } else {
          // Die Angabe der Anzahl dieses Teils fehlt!
          System.err.println("Fehlendes Attribut count bei Teil #" +
              strTeileNummer + " (Anzahl " + cEchteAnzahl + ")");
        }
      }
    }
  }
}

Wenn wir dieses Dokument über das XML-Dokument buecherregal.xml aus der XML-Referenz laufen lassen, erhalten wir die folgende Ausgabe:

Fehlendes Attribut count bei Teil #HC (Anzahl 8)

Das <teil> mit der Teilenummer #A ist nicht korrekt: Die echte Anzahl ist = 2 (der Zähler im Dokument ist 1)

Um dieses Programm zu kompilieren und zu starten, müssen Sie zunächst den Java-Parser Xerces vom Apache-XML-Projekt haben. Ursprünglich wurde das Programm mit dem Sun-JDK in der Version 1.3.1 getestet.

  

<< zurück vor >>

 

 

 

Tipp der data2type-Redaktion:
Zum Thema XML bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an:

  


Copyright © 2005 O'Reilly Verlag GmbH & Co. KG
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken.
Ansonsten unterliegt dieses Kapitel aus dem Buch "XML in a Nutshell" denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

O’Reilly Verlag GmbH & Co. KG, Balthasarstraße 81, 50670 Köln, kommentar(at)oreilly.de