2011-12-15 2 views
11

Ho il seguente file xml:Come leggere le proprietà dal file xml con java?

<resources> 
    <resource id="res001"> 
     <property name="propA" value="A" /> 
     <property name="propB" value="B" /> 
    </resource> 
    <resource id="res002"> 
     <property name="propC" value="C" /> 
     <property name="propD" value="D" /> 
    </resource> 
    <resource id="res003"> 
     <property name="propE" value="E" /> 
     <property name="propF" value="F" /> 
    </resource> 
</resources> 

Come posso fare qualcosa di simile con Java/XML:

Xml xml = new Xml("my.xml"); 
Resource res001 = xml.getResouceById("res003"); 
System.out.println("propF: " + res.getProperty("propF")); 

Quindi esso stampa:

F 

ho provato apache commons-configuration XMLConfiguration con XPathExpressionEngine, ma non riesco a farlo funzionare. Googled e trovato alcuni esempi, ma nessuno dei due avrebbe funzionato :( Sto cercando una soluzione in cui non ho bisogno di scorrere tutti gli elementi.

saluti, Alex

+0

Leggermente fuori tema, ma c'è un motivo particolare di memorizzare le proprietà come individuo elementi e non come attributi? '' –

+0

Non riconosco quel formato. Che cos'è? –

+0

Emil, Sembra molto naturale in questo modo. qualche altro suggerimento? – etxalpo

risposta

1

vorrei solo utilizzare JAXB per associare i dati in serie di oggetti che hanno struttura simile a un documento XML

Qualcosa come:.

@XmlRootElement("resources") 
public class Resources { 
    public List<Resource> resource = new ArrayList<Resource>(); // important, can't be left null 
} 
public class Resource { 
    @XmlAttribute public String id; 
    public List<Property> property; 
} 
// and so on 

una possibile Gotcha sia per quanto riguarda Lista serializzazione, ci sono due modalità, avvolto e scartato; nel tuo caso, vuoi "scartato". I Javadoc per le annotazioni dovrebbero mostrare annotazioni per definirlo.

+0

Sì, ma poi crea prima un XSD e genera i bean.http: //jaxb.java.net/tutorial/ –

+0

No, assolutamente no - se fosse necessario XSD, preferirei avere root canal. Invece, devi solo definire POJO (con setter e getter o campi pubblici) e usarlo. Nessun schema coinvolto. – StaxMan

1

Ci sono molti modi. Uno è quello di fare JDOM e xpath. Qualcosa di simile a questo (da questo articolo: http://onjava.com/onjava/2005/01/12/xpath.html):

SAXBuilder saxBuilder = 
    new SAXBuilder("org.apache.xerces.parsers.SAXParser"); 
org.jdom.Document jdomDocument = 
    saxBuilder.build(new File("somefile"); 
org.jdom.Attribute levelNode = 
    (org.jdom.Attribute)(XPath.selectSingleNode(
     jdomDocument, 
     "/resources/resource[@id='res003']/property[@name='propF']/@value")); 
System.out.println(levelNode.getValue()); 

non prova, ma dovrebbe funzionare. Per il tutorial su xpath vedere http://zvon.org/xxl/XPathTutorial/General/examples.html. È il tutorial migliore e più veloce.

Prestare attenzione al ciclo di vita del saxbuilder, se viene chiamato spesso.

0

Esistono diversi parser che è possibile utilizzare. Per me questi parser ha funzionato bene:

0

ho redommend il XStream.

Analizza l'XML nell'oggetto con lo stesso strutuct.

Chi XStream

Il vostro oggetto sarà:

List<Resources> 

mentre Resources con gli attributi, con setter e getter, id che è un oggetto Property con attibutes name e value.

Spero che questo aiuto

0

Se fossi in te, vorrei utilizzare un'interfaccia con i vostri metodi desiderati (getProperty, Resource, ecc) e fornire un'implementazione XPath.

10

Questo è banale, assumendo che si sia disposti a riscrivere il file delle proprietà nel formato standard Java. Supponete di avere quanto segue in un file chiamato props.xml:

<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> 
<properties> 
    <comment>This is a comment</comment> 
    <entry key="propA">A</entry> 
    <entry key="propB">B</entry> 
    <entry key="propC">C</entry> 
    <entry key="propD">D</entry> 
    <entry key="propE">E</entry> 
    <entry key="propF">F</entry> 
</properties> 

Poi leggi le proprietà del file in questo modo:

java.util.Properties prop = new Properties(); 
prop.loadFromXML(new FileInputStream("props.xml")); 
System.out.println(prop.getProperty("propF")); 
0

Grazie per tutte le risposte/suggerimenti! Ho provato alcune delle librerie xml di cui sopra e ho deciso di andare con la libreria XML Simple. Ho trovato particolarmente utile la classe di utilità "Dizionario", per evitare il looping di tutti gli elementi. Elegante e semplice :)

Di seguito è come l'ho usato. Spero che possa aiutare qualcun altro ...

saluti,

Alex

un esempio di lavoro (in Windows Vista):

finestra
package demo; 

import java.io.File; 

import org.simpleframework.xml.Serializer; 
import org.simpleframework.xml.core.Persister; 

public class Demo { 
    public static void main(String[] args) throws Exception { 
     File file = new File("c:\\temp\\resources.xml"); 
     Serializer serializer = new Persister(); 
     Resources resources = serializer.read(Resources.class, file); 

     Resource resource = resources.getResourceByName("res001"); 
     System.out.println(resource.getProperty("propA")); 
     System.out.println(resource.getProperty("propB")); 
    } 
} 

Console:

A-001 
B-001 

Resources.java

package demo; 

import org.simpleframework.xml.ElementList; 
import org.simpleframework.xml.Root; 
import org.simpleframework.xml.util.Dictionary; 

@Root(name="resources") 
public class Resources { 
    @ElementList(entry = "resource", inline = true) 
    private Dictionary<Resource> resources = new Dictionary<Resource>(); 

    public Resources(@ElementList(entry = "resource", inline = true) Dictionary<Resource> resources) { 
     this.resources = resources; 
} 

    public Resource getResourceByName(String name){ 
     return resources.get(name); 
    } 
} 

Resource.java

package demo; 

import org.simpleframework.xml.Attribute; 
import org.simpleframework.xml.ElementList; 
import org.simpleframework.xml.util.Dictionary; 
import org.simpleframework.xml.util.Entry; 

public class Resource implements Entry{ 
    @Attribute(name = "name") private final String name; 
    @ElementList(inline=true, name="property") private Dictionary<Property> properties; 

    public Resource(
        @Attribute(name = "name") String name, 
        @ElementList(inline=true, name="property") Dictionary<Property> properties) { 
      this.name = name; 
      this.properties = properties; 
    } 

    public String getName() { 
     return name; 
    } 

    public String getProperty(String name) { 
     return properties.get(name).getValue(); 
    } 
} 

Property.java

package demo; 

import org.simpleframework.xml.Attribute; 
import org.simpleframework.xml.Root; 
import org.simpleframework.xml.util.Entry; 

@Root 
public class Property implements Entry{ 
    @Attribute(name="name") private String name; 
    @Attribute(name="value") private String value; 

    public Property(@Attribute(name="name") String name, @Attribute(name="value") String value) { 
     this.name = name; 
     this.value = value; 
    } 

    public String getName() { 
     return name; 
    } 

    public String getValue() { 
     return value; 
    } 
} 

resources.xml

<resources> 
    <resource name="res001"> 
     <property name="propA" value="A-001" /> 
     <property name="propB" value="B-001" /> 
    </resource> 
    <resource name="res002"> 
     <property name="propA" value="A-002" /> 
     <property name="propB" value="B-002" /> 
    </resource> 
    <resource name="res003"> 
     <property name="propA" value="A-003" /> 
     <property name="propB" value="B-003" /> 
    </resource> 
</resources>