Мне нужно читать и писать в файл XML. Каков самый простой способ чтения и записи XML файлов с помощью Java?
Как читать и писать xml файлы?
Ответ 1
Вот быстрый пример DOM, который показывает, как читать и писать простой XML файл с его 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>
и 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)>
Сначала импортируйте эти:
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.*;
Вот несколько переменных, которые вам понадобятся:
private String role1 = null;
private String role2 = null;
private String role3 = null;
private String role4 = null;
private ArrayList<String> rolev;
Вот читатель (String xml - это имя вашего 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;
    }
И вот автор:
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 здесь:
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;
}
Добавьте несколько аксессуаров и мутаторов, и все готово!
Ответ 2
Вышеупомянутый ответ касается только анализатора DOM (который обычно читает весь файл в памяти и анализирует его, что для большого файла является проблемой), вы можете использовать SAX-парсер, который использует меньше памяти и быстрее (в любом случае это зависит от вашего кода).
SAX-парсер вызывает некоторые функции, когда он находит начало элемента, конец элемента, атрибут, текст между элементами и т.д., поэтому он может анализировать документ и в то же время вы получите то, что вам нужно.
Пример кода:
http://www.mkyong.com/java/how-to-read-xml-file-in-java-sax-parser/
Ответ 3
Написание XML с использованием JAXB (Java Architecture для привязки XML):
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();
          }
    }
}
		Ответ 4
Ответы охватывают только DOM/SAX и реализацию копирования в примере JAXB.
Однако, одна большая область, когда вы используете XML, отсутствует. Во многих проектах/программах необходимо хранить/извлекать некоторые основные структуры данных. В вашей программе уже есть классы для ваших хороших и блестящих бизнес-объектов/структур данных, вам просто нужен удобный способ преобразования этих данных в структуру XML, чтобы вы могли делать больше магии (хранить, загружать, отправлять, манипулировать с помощью XSLT).
Здесь XStream светит. Вы просто аннотируете классы, содержащие ваши данные, или если вы не хотите менять эти классы, вы настраиваете экземпляр XStream для сортировки (объекты → xml) или unmarshalling (xml → objects).
Внутренне XStream использует рефлексию, методы readObject и readResolve стандартной сериализации объектов Java.
Вы получите хороший и быстрый учебник здесь:
Чтобы дать краткий обзор того, как это работает, я также предоставляю некоторый пример кода, который объединяет и отменяет структуру данных.
Маршаллинг /unmarshalling происходит в методе main, остальное - это просто код для создания некоторых тестовых объектов и заполнения некоторых данных.
Очень просто настроить экземпляр xStream, а сортировка/разметка выполняется с помощью одной строки кода.
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;
    }
  }
}
		Ответ 5
Хорошо, уже имея DOM, JaxB и XStream в списке ответов, есть еще отличный способ читать и писать XML: Прогноз данных Вы можете отделить структуру XML и структуру Java, используя библиотеку, которая обеспечивает чтение и запись представлений в XML-данные как интерфейсы Java. Из учебников:
Учитывая некоторый реальный мир XML:
<weatherdata>
  <weather
    ... 
    degreetype="F"
    lat="50.5520210266113" lon="6.24060010910034" 
    searchlocation="Monschau, Stadt Aachen, NW, Germany" 
            ... >
    <current ... skytext="Clear" temperature="46"/>
  </weather>
</weatherdata>
С проецированием данных вы можете определить интерфейс проекции:
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();
}
И используйте экземпляры этого интерфейса, как POJO:
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());
}
Это работает даже для создания XML, выражения XPath могут быть доступны для записи.
Ответ 6
SAX-парсер работает по-разному с парсером DOM, он не загружает ни один XML-документ в память и не создает каких-либо объектных представлений XML-документа. Вместо этого анализатор SAX использует функцию обратного вызова (org.xml.sax.helpers.DefaultHandler) для информирования клиентов о структуре документа XML.
SAX Parser работает быстрее и использует меньше памяти, чем парсер DOM. См. Следующие методы обратного вызова SAX:
startDocument() и endDocument() - метод, вызываемый в начале и конце документа XML. startElement() и endElement() - метод, вызываемый в начале и конце элемента документа. characters() - метод, вызываемый текстовым содержимым между начальным и конечным тегами элемента XML-документа. 1. XML файл Создайте простой 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>
- Файл Java Используйте синтаксический анализатор SAX для анализа XML файла.
 
импортировать 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();
 }
   }
}
Результат
Start Element: компания 
Start Element: сотрудники 
Начальный элемент: имя пользователя 
Имя: yong 
End Element: имя пользователя 
Элемент Start: lastname 
Фамилия: mook kim 
End Element: lastname 
Начальный элемент: псевдоним 
Ник Имя: mkyong 
Конечный элемент: псевдоним 
и так далее...
Источник (MyKong) - http://www.mkyong.com/java/how-to-read-xml-file-in-java-sax-parser/