注: 私はEclipseLink JAXB (MOXy)のリーダーであり、JAXB (JSR-222)エキスパート グループのメンバーです。
私は適切な回避策を考え出そうとしていますが、以下は、@XmlCDATA
このユースケースをより簡単にサポートできるようにするためにアノテーションを拡張するための拡張リクエストです。
更新 #1
以下は、私があなたのユースケースに取り組んでいるアプローチです。MOXy を少し変更する必要があることはわかっていますが、まだ完全にテストする必要があります。次のリンクを使用して、この問題の進行状況を追跡できます。
DomHandler (CdataHandler)
JAXB にはDomHandler
、XML の外観をさらに制御できる の概念があります。必要に応じて、を活用してブロックDomHandler
を追加します。CDATA
package forum14145131;
import javax.xml.bind.ValidationEventHandler;
import javax.xml.bind.annotation.DomHandler;
import javax.xml.parsers.*;
import javax.xml.transform.Source;
import javax.xml.transform.dom.*;
import org.w3c.dom.*;
public class CdataHandler implements DomHandler<String, DOMResult> {
private static DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();;
@Override
public DOMResult createUnmarshaller(ValidationEventHandler veh) {
return new DOMResult();
}
@Override
public String getElement(DOMResult domResult) {
Document document = (Document) domResult.getNode();
return document.getDocumentElement().getTextContent();
}
@Override
public Source marshal(String string, ValidationEventHandler veh) {
try {
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.newDocument();
Node node;
if(string.contains("<") || string.contains("&") || string.contains("&")) {
node = document.createCDATASection(string);
} else {
node = document.createTextNode(string);
}
return new DOMSource(node);
} catch(Exception e) {
throw new RuntimeException(e);
}
}
}
埋め込む
@XmlAnyElement
注釈は、を指定するために使用されますDomHandler
。
package forum14145131;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
class Embed{
@XmlAnyElement(CdataHandler.class)
private String value; //THIS CAN BE CDATA OR NOT
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
詳細については
更新 #2
XmlAdapter
以下は、および を利用する既存の EclipseLink ライブラリを使用して、現在使用できるアプローチですCharacterEscapeHandler
。
XmlAdapter (CdataAdapter)
package forum14145131;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class CdataAdapter extends XmlAdapter<String, String> {
@Override
public String marshal(String string) throws Exception {
if(string.contains("&") || string.contains("<") || string.contains("\"")) {
return "<![CDATA[" + string + "]]>";
} else {
return string;
}
}
@Override
public String unmarshal(String string) throws Exception {
return string;
}
}
埋め込む
@XmlJavaTypeAdapter
注釈は、を指定するために使用されますXmlAdapter
。
package forum14145131;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
class Embed{
@XmlValue
@XmlJavaTypeAdapter(CdataAdapter.class)
private String value; //THIS CAN BE CDATA OR NOT
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
デモ
を指定する方法は次のとおりですCharacterEscapeHandler
。これは、 this のすべての文字エスケープをオーバーライドすることに注意してくださいMarshaller
。これは、そのCDATA
部分がエスケープされないようにするためです。製品コードの場合、このメソッドの実装は、この例で示されているものより強化する必要があります。
package forum14145131;
import java.io.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.eclipse.persistence.oxm.CharacterEscapeHandler;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Embed.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum14145131/input.xml");
Embed embed = (Embed) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(MarshallerProperties.CHARACTER_ESCAPE_HANDLER,
new CharacterEscapeHandler() {
@Override
public void escape(char[] ac, int i, int j, boolean flag,
Writer writer) throws IOException {
writer.write(ac, i, j);
}
});
marshaller.marshal(embed, System.out);
}
}
input.xml/出力
<?xml version="1.0" encoding="UTF-8"?>
<embed><![CDATA[Hello & World]]></embed>