私はJAXBを初めて使用するので、XMLを応答オブジェクトにアンマーシャルできるが、xpath式を使用できる方法があるかどうか知りたいです。問題は、サードパーティのWebサービスに電話をかけていて、受け取った応答に多くの詳細が含まれていることです。 XMLのすべての詳細を応答オブジェクトにマップしたくありません。特定のXPath式を使用して取得できるxmlからいくつかの詳細をマップし、それらを応答オブジェクトにマップしたいだけです。これを達成するのに役立つ注釈はありますか?
たとえば、次の応答を考えます
<root>
<record>
<id>1</id>
<name>Ian</name>
<AddressDetails>
<street> M G Road </street>
</AddressDetails>
</record>
</root>
ストリート名の取得のみに関心があるので、xpath式を使用して、「root/record/AddressDetails/street」を使用してストリートの値を取得し、それを応答オブジェクトにマップします
public class Response{
// How do i map this in jaxb, I do not wish to map record,id or name elements
String street;
//getter and setters
....
}
ありがとう
注:私は EclipseLink JAXB(MOXy) リードおよび JAXB(JST-222) エキスパートグループのメンバー。
この使用例では、MOXyの@XmlPath
拡張を使用できます。
応答
import javax.xml.bind.annotation.*;
import org.Eclipse.persistence.oxm.annotations.XmlPath;
@XmlRootElement(name="root")
@XmlAccessorType(XmlAccessType.FIELD)
public class Response{
@XmlPath("record/AddressDetails/street/text()")
String street;
//getter and setters
}
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
デモ
import Java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Response.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum17141154/input.xml");
Response response = (Response) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(response, System.out);
}
}
出力
<?xml version="1.0" encoding="UTF-8"?>
<root>
<record>
<AddressDetails>
<street> M G Road </street>
</AddressDetails>
</record>
</root>
詳細情報
ストリート名だけが必要な場合は、XPath式を使用して文字列として取得し、JAXBを忘れてください。複雑なJAXB機構は値を追加していません。
import javax.xml.xpath.*;
import org.xml.sax.InputSource;
public class XPathDemo {
public static void main(String[] args) throws Exception {
XPathFactory xpf = XPathFactory.newInstance();
XPath xpath = xpf.newXPath();
InputSource xml = new InputSource("src/forum17141154/input.xml");
String result = (String) xpath.evaluate("/root/record/AddressDetails/street", xml, XPathConstants.STRING);
System.out.println(result);
}
}
XMLドキュメントの中央にマップする場合は、次のようにします。
デモコード
StAXパーサーを使用して、ドキュメントの非整列化する部分に進み、そこからXMLStreamReader
を非整列化できます。
import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.transform.stream.StreamSource;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Response.class);
XMLInputFactory xif = XMLInputFactory.newFactory();
StreamSource xml = new StreamSource("src/forum17141154/input.xml");
XMLStreamReader xsr = xif.createXMLStreamReader(xml);
while(!(xsr.isStartElement() && xsr.getLocalName().equals("AddressDetails"))) {
xsr.next();
}
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBElement<Response> response = unmarshaller.unmarshal(xsr, Response.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(response, System.out);
}
}
応答
ドメインオブジェクトのマッピングは、マッピング先のXMLドキュメントのフラグメントを基準にして作成されます。
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
public class Response{
String street;
//getter and setters
}
出力
<?xml version="1.0" encoding="UTF-8"?>
<AddressDetails>
<street> M G Road </street>
</AddressDetails>
詳細情報