Jak odczytywać i zapisywać pliki xml?

Muszę odczytywać i zapisywać do i z pliku XML. Jaki jest najprostszy sposób odczytu i zapisu plików XML przy użyciu Javy?

Author: Paolo Forgia, 2011-09-10

6 answers

Oto szybki przykład DOM, który pokazuje, jak czytać i pisać prosty plik xml z jego dtd:

<?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>

I 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)>

Najpierw zaimportuj te:

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.*;

Oto kilka potrzebnych zmiennych:

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

Oto czytnik (String xml to nazwa Twojego pliku xml):

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;
    }

A tu autor:

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 jest tutaj:

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;
}

Dodaj kilka accesorów i mutatorów i gotowe!

 120
Author: Costis Aivalis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-29 23:03:56

Powyższa odpowiedź dotyczy tylko parsera DOM (który normalnie czyta cały plik w pamięci i analizuje go, co dla dużego pliku jest problemem), możesz użyć parsera SAX, który zużywa mniej pamięci i jest szybszy (w każdym razie to zależy od Twojego kodu).

Parser SAX wywołuje wywołanie niektórych funkcji, gdy znajdzie początek elementu, koniec elementu, atrybut, tekst między elementami itp., dzięki czemu może analizować dokument i jednocześnie weź to, czego potrzebujesz.

Jakiś przykład kod:

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

 10
Author: Diego C Nascimento,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-19 03:26:12

Zapis XML za pomocą 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();
          }

    }
}
 9
Author: Ran Adler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-29 06:33:16

Odpowiedzi dotyczą tylko DOM / SAX i implementacji copy paste przykładu JAXB.

Jednak brakuje jednego dużego obszaru, kiedy używasz XML. W wielu projektach / programach istnieje potrzeba przechowywania / pobierania niektórych podstawowych struktur danych. Twój program ma już klasy dla Twoich ładnych i błyszczących obiektów biznesowych / struktur danych, po prostu chcesz wygodny sposób konwersji tych danych do struktury XML, dzięki czemu możesz zrobić więcej magii na nim (przechowywać, ładować, wysyłać, manipulować z XSLT).

Tutaj świeci XStream. Po prostu dodajesz adnotacje do klas przechowujących Twoje dane, lub jeśli nie chcesz zmieniać tych klas, skonfigurujesz instancję XStream do sortowania (objects - > XML) lub unmarshalling (XML -> objects).

Wewnętrznie XStream wykorzystuje metody reflection, readObject i readResolve standardowej serializacji obiektów Java.

Dostajesz dobry i szybki tutorial tutaj :

Aby dać krótki przegląd tego, jak to działa, ja również podaj przykładowy kod, który określa i usuwa strukturę danych. Marshalling / unmarshalling odbywa się w metodzie main, reszta to tylko kod do generowania niektórych obiektów testowych i wypełniania do nich niektórych danych. Konfiguracja instancji xStream jest bardzo prosta, a marshalling / unmarshalling odbywa się za pomocą jednej linii kodu.

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;
    }
  }
}
 3
Author: Matthias,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-14 13:59:34

Ok, mając już DOM, JaxB i XStream na liście odpowiedzi, nadal istnieje zupełnie inny sposób odczytu i zapisu XML: projekcja danych {[5] } możesz oddzielić strukturę XML od struktury Java za pomocą biblioteki, która zapewnia odczytywalne i zapisywalne widoki do danych XML jako interfejsy Java. Z poradników :

Biorąc pod uwagę jakiś rzeczywisty XML:

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

Za pomocą projekcji danych można zdefiniować interfejs projekcji:

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();
}

I używać instancji ten interfejs tak jak 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());
}

To działa nawet przy tworzeniu XML, wyrażenia XPath mogą być zapisywalne.

 1
Author: Cfx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-27 21:52:43

SAX parser działa inaczej z parserem DOM, nie ładuje żadnego XML dokumentu do pamięci ani nie tworzy żadnej reprezentacji obiektu XML dokumentu. Zamiast tego parser SAX używa funkcji callback org.xml.sax.helpers.DefaultHandler do informowania klientów o strukturze dokumentu XML.

SAX Parser jest szybszy i zużywa mniej pamięci niż parser DOM. Patrz następujące metody wywołania zwrotnego SAX:

startDocument() and {[13] – - metoda wywoływana na początku i końcu dokumentu XML. startElement() i endElement() - Metoda wywołana na początku i końcu elementu dokumentu. {[16] – - metoda wywołana z zawartością tekstu pomiędzy znacznikami początku i końca elementu dokumentu XML.

  1. plik XML

Utwórz prosty plik XML.

<?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. parser XML:

Plik Java użyj parsera SAX do analizy pliku XML.

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();
        }

    }

}

Wynik

Element startowy: firma
Element startowy: staff
Element startowy: firstname
Imię : yong
End Element: firstname
Element startowy: lastname
Nazwisko: mook kim
End Element: lastname
Element startowy: Nick
Nick: mkyong
End Element: Nick
i tak dalej...

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

 0
Author: JavaDragon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-02 12:19:12