使用JAXB根据属性解析xml

问题描述:

我正在使用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 

不是一个集合属性。

有没有一个很好的方法来解决这个问题,例如一些注释?

注:我是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