注: 私はEclipseLink JAXB (MOXy)のリーダーであり、JAXB (JSR-222)エキスパート グループのメンバーです。
以下に、このユース ケースを処理する 2 つの方法を示します。1 つ目はコードが少し増えますが、任意の JAXB 実装で実行できます。2 つ目はコードが少ないですが、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;
}
}
入力.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 (MOXy)
MOXy の拡張機能を利用して、値を持つ属性を持つ要素@XmlPath
にマップします( http://blog.bdoughan.com/2011/03/map-to-element-based-on-attribute-value.htmlを参照)。Name
language
en
国
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
MOXy を 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);
}
}
入力.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>