Wie lese und schreibe ich XML-Dateien?

Antworten:

131

Hier ist ein kurzes DOM-Beispiel, das zeigt, wie eine einfache XML-Datei mit ihrem dtd gelesen und geschrieben wird:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE roles SYSTEM "roles.dtd">
<roles>
    <role1>User</role1>
    <role2>Author</role2>
    <role3>Admin</role3>
    <role4/>
</roles>

und der dtd:

<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT roles (role1,role2,role3,role4)>
<!ELEMENT role1 (#PCDATA)>
<!ELEMENT role2 (#PCDATA)>
<!ELEMENT role3 (#PCDATA)>
<!ELEMENT role4 (#PCDATA)>

Importieren Sie zuerst diese:

import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import org.xml.sax.*;
import org.w3c.dom.*;

Hier sind einige Variablen, die Sie benötigen:

private String role1 = null;
private String role2 = null;
private String role3 = null;
private String role4 = null;
private ArrayList<String> rolev;

Hier ist ein Reader (String xml ist der Name Ihrer XML-Datei):

public boolean readXML(String xml) {
        rolev = new ArrayList<String>();
        Document dom;
        // Make an  instance of the DocumentBuilderFactory
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try {
            // use the factory to take an instance of the document builder
            DocumentBuilder db = dbf.newDocumentBuilder();
            // parse using the builder to get the DOM mapping of the    
            // XML file
            dom = db.parse(xml);

            Element doc = dom.getDocumentElement();

            role1 = getTextValue(role1, doc, "role1");
            if (role1 != null) {
                if (!role1.isEmpty())
                    rolev.add(role1);
            }
            role2 = getTextValue(role2, doc, "role2");
            if (role2 != null) {
                if (!role2.isEmpty())
                    rolev.add(role2);
            }
            role3 = getTextValue(role3, doc, "role3");
            if (role3 != null) {
                if (!role3.isEmpty())
                    rolev.add(role3);
            }
            role4 = getTextValue(role4, doc, "role4");
            if ( role4 != null) {
                if (!role4.isEmpty())
                    rolev.add(role4);
            }
            return true;

        } catch (ParserConfigurationException pce) {
            System.out.println(pce.getMessage());
        } catch (SAXException se) {
            System.out.println(se.getMessage());
        } catch (IOException ioe) {
            System.err.println(ioe.getMessage());
        }

        return false;
    }

Und hier ein Schriftsteller:

public void saveToXML(String xml) {
    Document dom;
    Element e = null;

    // instance of a DocumentBuilderFactory
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    try {
        // use factory to get an instance of document builder
        DocumentBuilder db = dbf.newDocumentBuilder();
        // create instance of DOM
        dom = db.newDocument();

        // create the root element
        Element rootEle = dom.createElement("roles");

        // create data elements and place them under root
        e = dom.createElement("role1");
        e.appendChild(dom.createTextNode(role1));
        rootEle.appendChild(e);

        e = dom.createElement("role2");
        e.appendChild(dom.createTextNode(role2));
        rootEle.appendChild(e);

        e = dom.createElement("role3");
        e.appendChild(dom.createTextNode(role3));
        rootEle.appendChild(e);

        e = dom.createElement("role4");
        e.appendChild(dom.createTextNode(role4));
        rootEle.appendChild(e);

        dom.appendChild(rootEle);

        try {
            Transformer tr = TransformerFactory.newInstance().newTransformer();
            tr.setOutputProperty(OutputKeys.INDENT, "yes");
            tr.setOutputProperty(OutputKeys.METHOD, "xml");
            tr.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
            tr.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "roles.dtd");
            tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");

            // send DOM to file
            tr.transform(new DOMSource(dom), 
                                 new StreamResult(new FileOutputStream(xml)));

        } catch (TransformerException te) {
            System.out.println(te.getMessage());
        } catch (IOException ioe) {
            System.out.println(ioe.getMessage());
        }
    } catch (ParserConfigurationException pce) {
        System.out.println("UsersXML: Error trying to instantiate DocumentBuilder " + pce);
    }
}

getTextValue ist da:

private String getTextValue(String def, Element doc, String tag) {
    String value = def;
    NodeList nl;
    nl = doc.getElementsByTagName(tag);
    if (nl.getLength() > 0 && nl.item(0).hasChildNodes()) {
        value = nl.item(0).getFirstChild().getNodeValue();
    }
    return value;
}

Fügen Sie ein paar Accessoren und Mutatoren hinzu und Sie sind fertig!

Costis Aivalis
quelle
6
Wird die dtd-Datei benötigt, damit dies funktioniert, oder können wir XML ohne dtd lesen? Wenn dtd benötigt wird, können wir ein dtd einfach aus xml generieren, anstatt alles selbst zu tippen?
3
Sie könnten die dtd-Datei weglassen. Stellen Sie sicher, dass Sie auch den Verweis darauf aus der XML-Datei entfernen: <! DOCTYPE role SYSTEM "role.dtd">. Sie können kostenlose dtd-Generatoranwendungen finden oder einen Online-Dienst nutzen. Sie generieren zunächst eine "gut genug" dtd-Datei. Normalerweise müssen Sie es ein wenig ändern.
Costis Aivalis
Tolles Beispiel! Ich hatte ein kleines Problem mit der Funktion getTextValue (). Sie sollte eine Zeichenfolge mit der Länge Null anstelle von Null zurückgeben, wenn der Knoten leer ist. Ich musste hinzufügen "if (value == null) value =" ";" vor dem "Rückgabewert", sonst würde es beim Schreiben der XML-Zeichenfolge abstürzen.
Herr Ed
@CostisAivalis könnten Sie mir bitte sagen , wie zu analysieren und zu speichern svg in Batik hier . Ich habe Probleme, zwischen XML und Batiks Arbeitsweise zu unterscheiden.
Mirwise Khan
14

Schreiben von XML mit JAXB (Java Architecture for XML Binding):

http://www.mkyong.com/java/jaxb-hello-world-example/

package com.mkyong.core;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Customer {

    String name;
    int age;
    int id;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    @XmlElement
    public void setAge(int age) {
        this.age = age;
    }

    public int getId() {
        return id;
    }

    @XmlAttribute
    public void setId(int id) {
        this.id = id;
    }

} 

package com.mkyong.core;

import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

public class JAXBExample {
    public static void main(String[] args) {

      Customer customer = new Customer();
      customer.setId(100);
      customer.setName("mkyong");
      customer.setAge(29);

      try {

        File file = new File("C:\\file.xml");
        JAXBContext jaxbContext = JAXBContext.newInstance(Customer.class);
        Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

        // output pretty printed
        jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        jaxbMarshaller.marshal(customer, file);
        jaxbMarshaller.marshal(customer, System.out);

          } catch (JAXBException e) {
        e.printStackTrace();
          }

    }
}
Ran Adler
quelle
11

Die obige Antwort bezieht sich nur auf den DOM-Parser (der normalerweise die gesamte Datei im Speicher liest und analysiert, was für eine große Datei ein Problem ist). Sie können einen SAX-Parser verwenden, der weniger Speicher benötigt und schneller ist (dies hängt jedoch von Ihrem ab Code).

Der SAX-Parser ruft einige Funktionen zurück, wenn er einen Anfang des Elements, ein Ende des Elements, ein Attribut, einen Text zwischen Elementen usw. findet, damit er das Dokument analysieren kann und gleichzeitig das erhält, was Sie benötigen.

Ein Beispielcode:

http://www.mkyong.com/java/how-to-read-xml-file-in-java-sax-parser/

Diego C Nascimento
quelle
4

Die Antworten beziehen sich nur auf DOM / SAX und eine Copy-Paste-Implementierung eines JAXB-Beispiels.

Es fehlt jedoch ein großer Bereich, in dem Sie XML verwenden. In vielen Projekten / Programmen müssen einige grundlegende Datenstrukturen gespeichert / abgerufen werden. Ihr Programm verfügt bereits über Klassen für Ihre schönen und glänzenden Geschäftsobjekte / Datenstrukturen. Sie möchten nur eine bequeme Möglichkeit, diese Daten in eine XML-Struktur zu konvertieren, damit Sie mehr Magie darauf anwenden können (Speichern, Laden, Senden, Bearbeiten mit XSLT). .

Hier strahlt XStream. Sie kommentieren einfach die Klassen, in denen sich Ihre Daten befinden, oder konfigurieren eine XStream-Instanz für das Marshalling (Objekte -> XML) oder das Unmarshalling (XML -> Objekte), wenn Sie diese Klassen nicht ändern möchten.

Intern verwendet XStream Reflection, die Methoden readObject und readResolve der Standard-Serialisierung von Java-Objekten.

Sie erhalten eine gute und schnelle Tutorial hier :

Um einen kurzen Überblick über die Funktionsweise zu geben, stelle ich auch einen Beispielcode bereit, der eine Datenstruktur marshallt und demontiert. Das Marshalling / Unmarshalling erfolgt alle in der mainMethode, der Rest ist nur Code, um einige Testobjekte zu generieren und einige Daten in diese zu füllen . Es ist sehr einfach, die xStreamInstanz zu konfigurieren, und das Marshalling / Unmarshalling erfolgt mit jeweils einer Codezeile.

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import com.thoughtworks.xstream.XStream;

public class XStreamIsGreat {

  public static void main(String[] args) {
    XStream xStream = new XStream();
    xStream.alias("good", Good.class);
    xStream.alias("pRoDuCeR", Producer.class);
    xStream.alias("customer", Customer.class);

    Producer a = new Producer("Apple");
    Producer s = new Producer("Samsung");
    Customer c = new Customer("Someone").add(new Good("S4", 10, new BigDecimal(600), s))
        .add(new Good("S4 mini", 5, new BigDecimal(450), s)).add(new Good("I5S", 3, new BigDecimal(875), a));
    String xml = xStream.toXML(c); // objects -> xml
    System.out.println("Marshalled:\n" + xml);
    Customer unmarshalledCustomer = (Customer)xStream.fromXML(xml); // xml -> objects
  }

  static class Good {
    Producer producer;

    String name;

    int quantity;

    BigDecimal price;

    Good(String name, int quantity, BigDecimal price, Producer p) {
      this.producer = p;
      this.name = name;
      this.quantity = quantity;
      this.price = price;
    }

  }

  static class Producer {
    String name;

    public Producer(String name) {
      this.name = name;
    }
  }

  static class Customer {
    String name;

    public Customer(String name) {
      this.name = name;
    }

    List<Good> stock = new ArrayList<Good>();

    Customer add(Good g) {
      stock.add(g);
      return this;
    }
  }
}
Matthias
quelle
1

Ok, da DOM, JaxB und XStream bereits in der Liste der Antworten enthalten sind, gibt es immer noch eine völlig andere Möglichkeit, XML zu lesen und zu schreiben: Datenprojektion Sie können die XML-Struktur und die Java-Struktur mithilfe einer Bibliothek entkoppeln, die Lese- und beschreibbare Ansichten bereitstellt zu den XML-Daten als Java-Schnittstellen. Aus den Tutorials :

Angesichts einiger realer XML-Daten:

<weatherdata>
  <weather
    ... 
    degreetype="F"
    lat="50.5520210266113" lon="6.24060010910034" 
    searchlocation="Monschau, Stadt Aachen, NW, Germany" 
            ... >
    <current ... skytext="Clear" temperature="46"/>
  </weather>
</weatherdata>

Mit der Datenprojektion können Sie eine Projektionsschnittstelle definieren:

public interface WeatherData {

@XBRead("/weatherdata/weather/@searchlocation")   
String getLocation();

@XBRead("/weatherdata/weather/current/@temperature")
int getTemperature();

@XBRead("/weatherdata/weather/@degreetype")
String getDegreeType();

@XBRead("/weatherdata/weather/current/@skytext")
String getSkytext();

/**
 * This would be our "sub projection". A structure grouping two attribute
 * values in one object.
 */
interface Coordinates {
    @XBRead("@lon")
    double getLongitude();

    @XBRead("@lat")
    double getLatitude();
}

@XBRead("/weatherdata/weather")
Coordinates getCoordinates();
}

Und verwenden Sie Instanzen dieser Schnittstelle genau wie POJOs:

private void printWeatherData(String location) throws IOException {

final String BaseURL = "http://weather.service.msn.com/find.aspx?outputview=search&weasearchstr=";

// We let the projector fetch the data for us
WeatherData weatherData = new XBProjector().io().url(BaseURL + location).read(WeatherData.class);

// Print some values
System.out.println("The weather in " + weatherData.getLocation() + ":");
System.out.println(weatherData.getSkytext());
System.out.println("Temperature: " + weatherData.getTemperature() + "°"
                                   + weatherData.getDegreeType());

// Access our sub projection
Coordinates coordinates = weatherData.getCoordinates();
System.out.println("The place is located at " + coordinates.getLatitude() + ","
                                              + coordinates.getLongitude());
}

Dies funktioniert auch beim Erstellen von XML. Die XPath-Ausdrücke können beschreibbar sein.

Cfx
quelle
0

SAXDer Parser arbeitet anders mit einem DOMParser. Er lädt weder ein XMLDokument in den Speicher noch erstellt er eine Objektdarstellung des XMLDokuments. Stattdessen verwendet der SAXParser die Rückruffunktion, org.xml.sax.helpers.DefaultHandlerum Clients über die XMLDokumentstruktur zu informieren .

SAXDer Parser ist schneller und benötigt weniger Speicher als der DOMParser. Siehe folgende SAXRückrufmethoden:

startDocument()und endDocument()- Methode, die am Anfang und Ende eines XML-Dokuments aufgerufen wird. startElement()und endElement()- Methode, die am Anfang und Ende eines Dokumentelements aufgerufen wird. characters()- Methode, die mit dem Textinhalt zwischen den Start- und End-Tags eines XML-Dokumentelements aufgerufen wird.

  1. XML-Datei

Erstellen Sie eine einfache XML-Datei.

<?xml version="1.0"?>
<company>
    <staff>
        <firstname>yong</firstname>
        <lastname>mook kim</lastname>
        <nickname>mkyong</nickname>
        <salary>100000</salary>
    </staff>
    <staff>
        <firstname>low</firstname>
        <lastname>yin fong</lastname>
        <nickname>fong fong</nickname>
        <salary>200000</salary>
    </staff>
</company>
  1. XML-Parser:

Java-Datei Verwenden Sie den SAX-Parser, um die XML-Datei zu analysieren.

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class ReadXMLFile {
    public static void main(String argv[]) {

        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser saxParser = factory.newSAXParser();

            DefaultHandler handler = new DefaultHandler() {
                boolean bfname = false;
                boolean blname = false;
                boolean bnname = false;
                boolean bsalary = false;

                public void startElement(String uri, String localName,String qName, 
                            Attributes attributes) throws SAXException {

                    System.out.println("Start Element :" + qName);

                    if (qName.equalsIgnoreCase("FIRSTNAME")) {
                        bfname = true;
                    }

                    if (qName.equalsIgnoreCase("LASTNAME")) {
                        blname = true;
                    }

                    if (qName.equalsIgnoreCase("NICKNAME")) {
                        bnname = true;
                    }

                    if (qName.equalsIgnoreCase("SALARY")) {
                        bsalary = true;
                    }

                }

                public void endElement(String uri, String localName,
                    String qName) throws SAXException {

                    System.out.println("End Element :" + qName);

                }

                public void characters(char ch[], int start, int length) throws SAXException {

                    if (bfname) {
                        System.out.println("First Name : " + new String(ch, start, length));
                        bfname = false;
                    }

                    if (blname) {
                        System.out.println("Last Name : " + new String(ch, start, length));
                        blname = false;
                    }

                    if (bnname) {
                        System.out.println("Nick Name : " + new String(ch, start, length));
                        bnname = false;
                    }

                    if (bsalary) {
                        System.out.println("Salary : " + new String(ch, start, length));
                        bsalary = false;
                    }

                }

            };

            saxParser.parse("c:\\file.xml", handler);

        } catch (Exception e) {
           e.printStackTrace();
        }

    }

}

Ergebnis

Start Element: Firma
Start Element: Mitarbeiter
Start Element: Vorname
Vorname: yong
End Element: Vorname
Start Element: Nachname
Nachname: Mook kim
End Element: Nachname
Start Element: Spitznamen
Nick Name: mkyong
End Element: Spitznamen
und so weiter .. .

Quelle (MyKong) - http://www.mkyong.com/java/how-to-read-xml-file-in-java-sax-parser/

JavaDragon
quelle