2012-07-20 185 views
3

我正在使用JAXB解析一些xml。使用JAXB根據屬性解析xml

<countries> 
    <Name language="en">Australia</Name> 
    <Name language="se">Australien</Name> 
</countries> 

如果我在我的課的國家使用

@XmlElement(name = "Name", required = true) 
    protected List<Name> name; 

一切正常。 不過,我想只得到其中language =「EN」

所以我在國家階層有

protected String name 

不是一個集合屬性。

有沒有一個很好的方法來解決這個問題,例如一些註釋?

回答

4

注:我是EclipseLink JAXB (MOXy)鉛和JAXB (JSR-222)專家組

的成員,以下是你可以處理這個用例有兩種方式。第一個是更多的代碼,但可以通過任何JAXB實現來完成。第二個代碼較少,但需要使用EclipseLink JAXB(MOXy)。

選項1 - 任何JAXB(JSR-222)實現

演示

你可以使用一個過濾的流閱讀器來過濾掉不需要的元素,讓你的JAXB實現解組那。

package forum11586106; 

import javax.xml.bind.*; 
import javax.xml.stream.*; 
import javax.xml.transform.stream.StreamSource; 

public class Demo { 

    private static final String LANGUAGE_CODE = "en"; 

    public static void main(String[] args) throws Exception { 
     XMLInputFactory xif = XMLInputFactory.newFactory(); 
     XMLStreamReader xsr = xif.createXMLStreamReader(new StreamSource("src/forum11586106/input.xml")); 
     xsr = xif.createFilteredReader(xsr, new StreamFilter() { 

      private boolean isReading = true; 

      @Override 
      public boolean accept(XMLStreamReader reader) { 
       if(reader.isStartElement() && "Name".equals(reader.getLocalName())) { 
        isReading = LANGUAGE_CODE.equals(reader.getAttributeValue("", "language")); 
        return isReading; 
       } else if(reader.isEndElement() && !isReading) { 
        isReading = true; 
        return false; 
       } 

       return true; 
      }}); 

     JAXBContext jc = JAXBContext.newInstance(Countries.class); 
     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     Countries countries = (Countries) unmarshaller.unmarshal(xsr); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(countries, System.out); 
    } 

} 

國家

package forum11586106; 

import javax.xml.bind.annotation.*; 

@XmlRootElement 
public class Countries { 

    private String name; 

    @XmlElement(name="Name") 
    public String getName() { 
     return name; 
    } 

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

} 

的input.xml

這種方法的語言屬性不包含在輸出:

<countries> 
    <Name language="en">Australia</Name> 
    <Name language="se">Australien</Name> 
</countries> 

輸出

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<countries> 
    <Name>Australia</Name> 
</countries> 

選項#2 - 的EclipseLink JAXB(莫西)

我們將利用莫西的@XmlPath擴展映射到具有languageName元素屬性值爲en(請參閱http://blog.bdoughan.com/2011/03/map-to-element-based-on-attribute-value.html)。

國家

package forum11586106; 

import javax.xml.bind.annotation.*; 
import org.eclipse.persistence.oxm.annotations.XmlPath; 

@XmlRootElement 
public class Countries { 

    private String name; 

    @XmlPath("Name[@language='en']/text()") 
    public String getName() { 
     return name; 
    } 

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

} 

jaxb.properties

要使用莫西爲您的JAXB提供你需要包括一個文件在同一個包爲您的域模型稱爲jaxb.properties與以下條目(請參閱:http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html)。

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory 

演示

這種方法的元件的過濾是由@XmlPath映射處理,因此運行時部分變得簡單得多。注意只使用標準的JAXB運行時API。

package forum11586106; 

import java.io.File; 
import javax.xml.bind.*; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(Countries.class); 

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     File xml = new File("src/forum11586106/input.xml"); 
     Countries countries = (Countries) unmarshaller.unmarshal(xml); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(countries, System.out); 
    } 

} 

input.xml中

<countries> 
    <Name language="en">Australia</Name> 
    <Name language="se">Australien</Name> 
</countries> 

輸出

這種方法的language屬性被包括在輸出:

<?xml version="1.0" encoding="UTF-8"?> 
<countries> 
    <Name language="en">Australia</Name> 
</countries> 
+0

謝謝!第一個版本完美運行。我通常不使用Eclipse,但我嘗試過,但無法讓MOXy版本正常工作。 – Patrik 2012-07-26 06:53:09

+0

@PatrikNilsson - 您需要確保您使用的是EclipseLink 2.3或更高版本(當前版本爲EclipseLink 2.4)。您可以從以下網址下載獨立版本的EclipseLink:http://www.eclipse.org/eclipselink/downloads/ – 2012-07-26 15:23:37