2011-09-10 1 views

risposta

116

Ecco un esempio DOM rapida che mostra come leggere e scrivere un semplice file XML con la sua 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> 

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

Prima di importazione questi:

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

Ecco alcune variabili che è necessario:

Ecco un lettore (stringa XML è il nome del file 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; 
    } 

E qui uno scrittore:

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 è qui:

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

Aggiungi alcuni accessori e mutatori e il gioco è fatto!

+5

è il file DTD necessaria per far funzionare tutto questo o possiamo leggere xml senza il dtd? se dtd è necessario possiamo generare facilmente un dtd da xml invece di digitarlo tutto da soli? –

+3

Si potrebbe lasciare il file dtd. Assicurati di eliminare anche il riferimento ad esso dal file xml: . È possibile trovare applicazioni di generatore dtd gratuite o utilizzare un servizio online. Iniziano a generare un file dtd "abbastanza buono". Di solito dovrai modificarlo un po '. –

+1

Grazie per la risposta. :) –

10

La risposta sopra tratta solo con parser DOM (che normalmente legge l'intero file in memoria e lo analizza, per un file grande è un problema), è possibile utilizzare un parser SAX che utilizza meno memoria ed è più veloce (in ogni caso dipende dal tuo codice).

SAX parser richiamata alcune funzioni quando trovare un inizio di elemento, fine del elemento, attributo, testo tra gli elementi, ecc, in modo che possa analizzare il documento e, allo stesso tempo si ottenere quello che ti serve.

qualche esempio di codice:

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

8

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

    } 
} 
3

Le risposte coprono solo DOM/SAX e una implementazione di copia incolla di un esempio JAXB.

Tuttavia, manca una grande area di quando si utilizza XML. In molti progetti/programmi è necessario archiviare/recuperare alcune strutture di dati di base. Il tuo programma ha già una classe per i tuoi oggetti business/strutture di dati belle e lucenti, vuoi solo un modo comodo per convertire questi dati in una struttura XML in modo da poter fare più magia su di essa (memorizzare, caricare, inviare, manipolare con XSLT) .

Qui è dove XStream brilla. È sufficiente annotare le classi contenenti i dati oppure, se non si desidera modificare tali classi, configurare un'istanza XStream per il marshalling (oggetti -> xml) o unmarshalling (xml -> oggetti).

XStream utilizza la riflessione, i metodi readObject e readResolve della serializzazione di oggetti Java standard.

Si ottiene una buona e veloce tutorial di here:

Per dare una breve panoramica di come funziona, ho anche fornire alcuni esempi di codice che Marshalls e unmarshalls una struttura di dati. Il marshalling/unmarshalling avviene tutto nel metodo main, il resto è solo codice per generare alcuni oggetti di test e compilare alcuni dati su di essi. È semplicissimo configurare l'istanza xStream e il marshalling/unmarshalling viene eseguito con una riga di codice ciascuna.

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

Ok, già avendo DOM, JAXB e XStream nella lista delle risposte, c'è ancora un modo completamente diverso di leggere e scrivere XML: Data projection È possibile separare la struttura XML e la struttura Java utilizzando una libreria che fornisce viste leggibili e scrivibili ai dati XML come interfacce Java. Dal tutorials:

Dato alcuni XML mondo reale:

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

Con proiezione dei dati è possibile definire un'interfaccia di proiezione:

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

E utilizzare le istanze di questa interfaccia proprio come 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()); 
} 

Questo funziona anche per la creazione di XML, le espressioni XPath possono essere wri tavolo.

0

Il parser SAX funziona in modo diverso con un parser DOM, non carica alcun documento XML in memoria né crea alcuna rappresentazione dell'oggetto del documento XML. Invece, il parser SAX utilizza la funzione di callback (org.xml.sax.helpers.DefaultHandler) per informare i clienti della struttura del documento XML.

SAX Parser è più veloce e utilizza meno memoria del parser DOM. Vedere i seguenti metodi di callback SAX:

startDocument() e endDocument() - Metodo chiamato all'inizio e alla fine di un documento XML. startElement() e endElement() - Metodo chiamato all'inizio e alla fine di un elemento del documento. characters() - Metodo chiamato con il contenuto del testo tra i tag di inizio e di fine di un elemento di documento XML. 1. File XML Creare un semplice file 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. Java file di Usa SAX parser per analizzare il file XML.

javax.xml.parsers importazione.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(); 
} 


    } 

} 

Risultato

Inizio Elemento: azienda
Inizio Elemento: personale
Inizio Elemento: cognome
Nome: Yong
Fine Elemento: cognome
Inizio Elemento: cognome
Cognome : mook kim
Elemento terminale: cognome
Inizio Elemento: nick
Nick Nome: mkyong
Fine Elemento: nick
e così via ...

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