オブジェクトvalue
があります。これは、何らかのタイプの@XmlRootElement
-注釈付きかどうか。それをXMLにマーシャリングしたいと思います。
String value1 = "test";
assertEquals("<foo>test</foo>", toXml("foo", value1));
// ...
@XmlRootElement
class Bar {
public String bar = "test";
}
assertEquals("<foo><bar>test</bar></foo>", toXml("foo", new Bar()));
JAXBの既存の機能でそれを実行できますか、それともカスタムアナライザーを作成する必要がありますか?
JAXBIntrospectorを利用して、次のことを実行できます。
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBIntrospector;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.namespace.QName;
public class Demo {
public static void main(String[] args) throws Exception {
Object value = "Hello World";
//Object value = new Bar();
JAXBContext jc = JAXBContext.newInstance(String.class, Bar.class);
JAXBIntrospector introspector = jc.createJAXBIntrospector();
Marshaller marshaller = jc.createMarshaller();
if(null == introspector.getElementName(value)) {
JAXBElement jaxbElement = new JAXBElement(new QName("ROOT"), Object.class, value);
marshaller.marshal(jaxbElement, System.out);
} else {
marshaller.marshal(value, System.out);
}
}
@XmlRootElement
public static class Bar {
}
}
上記のコードでは、JAXBElementがマーシャリングされると、適切なスキーマタイプに対応するxsi:type属性で修飾されます。
<ROOT
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">Hello World</ROOT>
資格をなくすには、JAXBElementを作成する行を次のように変更するだけです。
JAXBElement jaxbElement = new JAXBElement(new QName("ROOT"), value.getClass(), value);
これにより、次のXMLが生成されます。
<ROOT>Hello World</ROOT>
これは、String
である_value1
_をマーシャリングする方法です。 yourObject.getClass()
をJAXBElement
コンストラクタに渡すことができ、_value1
_:
_try {
JAXBContext jc = JAXBContext.newInstance();
Marshaller m = jc.createMarshaller();
String value1 = "test";
JAXBElement jx = new JAXBElement(new QName("foo"), value1.getClass(), value1);
m.marshal(jx, System.out);
} catch (JAXBException ex) {
ex.printStackTrace();
}
_
これは_@XmlRootElement
_を使用しなくても機能します。上記のコードの結果は次のとおりです。
_<?xml version="1.0" encoding="UTF-8" standalone="yes"?><foo>test</foo>
_
一方、これはBar
オブジェクトでは機能しません:_javax.xml.bind.JAXBException: myPackage.Bar is not known to this context
_。ただし、Bar
から値を取得し、オブジェクト自体ではなく、それを使用してJAXBElement
を作成できます。
私はそれを行う一般的な方法を見つけられませんでした。これが私の一般的な解決策です。
import javax.xml.bind.*;
import javax.xml.namespace.QName;
import javax.xml.transform.stream.StreamSource;
import Java.io.StringReader;
import Java.io.StringWriter;
public class XMLConverter {
/**
* Serialize object to XML string
* @param object object
* @param <T> type
* @return
*/
public static <T> String marshal(T object) {
try {
StringWriter stringWriter = new StringWriter();
JAXBContext jc = JAXBContext.newInstance(object.getClass());
Marshaller m = jc.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
QName qName = new QName(object.getClass().getCanonicalName(), object.getClass().getSimpleName());
JAXBElement<T> root = new JAXBElement(qName, object.getClass(), object);
m.marshal(root, stringWriter);
return stringWriter.toString();
} catch (Exception e) {
// log the exception
}
return null;
}
/**
* Deserialize XML string back to object
* @param content XML content
* @param clasz class
* @param <T> type
* @return
*/
public static <T> T unMarshal(final String content, final Class<T> clasz) {
try {
JAXBContext jc = JAXBContext.newInstance(clasz);
Unmarshaller u = jc.createUnmarshaller();
return u.unmarshal(new StreamSource(new StringReader(content)), clasz).getValue();
} catch (Exception e) {
// log the exception
}
return null;
}
}
@XmlRootElement
の注釈が付いていない場合、JAXBにはマーシャリングに十分な情報がありません。最初にJAXBElement
でラップする必要があります。
オブジェクトを適切なJAXBElement
でラップする方法を見つけるために、いくつかの反射的な方法を実行できますか?