使用JAXB根据属性解析xml [英] Parse xml based on attributes using JAXB
问题描述
我正在使用JAXB解析一些xml.
I am using JAXB to parse some xml.
<countries>
<Name language="en">Australia</Name>
<Name language="se">Australien</Name>
</countries>
如果我在所在国家/地区使用
If I in my class Countries use
@XmlElement(name = "Name", required = true)
protected List<Name> name;
一切正常. 但是我只想获取language ="en"
everything works. However I would like to only get the attribute where language="en"
所以我在我的国家/地区课程中有
So I in my Countries class have
protected String name
不是收藏集.
例如,是否可以通过一些注释来解决此问题?
Is there a good way to solve this with some annotation for example?
推荐答案
注意:我是 JAXB(JSR-222) 专家组
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group
以下是您处理此用例的两种方法.首先是更多代码,但是可以用任何JAXB实现来完成.第二个是更少的代码,但是需要您使用EclipseLink JAXB(MOXy).
Below are two ways you could handle this use case. The first is a little more code but could be done with any JAXB implementation. The second is less code, but requires you use EclipseLink JAXB (MOXy).
选项#1-任何JAXB(JSR-222)的实现
演示
Demo
您可以使用过滤的流读取器过滤掉不需要的元素,并使JAXB实现取消编组.
You could use a filtered stream reader to filter out the unwanted elements and have your JAXB implementation unmarshal that.
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);
}
}
国家/地区
Countries
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
input.xml
使用这种方法,输出中不包含language属性:
With this approach the language attribute is not included in the output:
<countries>
<Name language="en">Australia</Name>
<Name language="se">Australien</Name>
</countries>
输出
Output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<countries>
<Name>Australia</Name>
</countries>
选项#2-ECLIPSELINK JAXB(MOXy)
我们将利用MOXy的@XmlPath
扩展名映射到具有值en
的language
属性的Name
元素(请参阅
We will leverage MOXy's @XmlPath
extension to map to the Name
element that has a language
attribute with value en
(see http://blog.bdoughan.com/2011/03/map-to-element-based-on-attribute-value.html).
国家/地区
Countries
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.properties
要将MOXy用作JAXB提供程序,您需要在与域模型相同的软件包中包含一个名为jaxb.properties
的文件,并带有以下条目(请参阅:
To use MOXy as your JAXB provider you need to include a file called jaxb.properties
in the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html).
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
演示
Demo
使用这种方法,元素过滤由@XmlPath
映射处理,因此运行时部分变得更加简单.请注意如何仅使用标准的JAXB运行时API.
With this approach the element filtering is handled by the @XmlPath
mapping, so the runtime portion becomes much simpler. Note how only the standard JAXB runtime APIs are used.
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
input.xml
<countries>
<Name language="en">Australia</Name>
<Name language="se">Australien</Name>
</countries>
输出
Output
通过这种方法,language
属性包含在输出中:
With this approach the language
attribute is included in the output:
<?xml version="1.0" encoding="UTF-8"?>
<countries>
<Name language="en">Australia</Name>
</countries>
这篇关于使用JAXB根据属性解析xml的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!