備註:我是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
下面是一個辦法,你Ç一個使用今天使用現有的EclipseLink庫利用的XmlAdapter
和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
。注意這將覆蓋此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>
感謝您的答覆。可能你已經考慮過了,但考慮到上述問題,建議的增強解決方案仍然存在相同的問題。即使我們設置了@XmlCDATA(XmlCDATAType.Optional),如果值是CDATA,問題(如何動態識別)仍然存在。或者,在使用@XmlCDATA(XmlCDATAType.Optional)時,如何決定是否渲染CDATA,您有任何想法。再次感謝。 – user1946448
@ user1946448 - 沒問題。我用另一種方法更新了我的答案,但是它需要對MOXY進行一些小改動,我仍然需要進行全面測試。爲了確定CDATA塊的存在,我只是要檢查是否存在'',''''或''',這對您的用例足夠了嗎? –
我衷心感謝您的更新。 #2,CharacterEscapeHandler不會逃避所有角色,也可能是你說它需要「加強」的原因。你認爲這並不是逃避所有角色的問題嗎?如果是這樣,我們可以使用一些默認轉義模式並修改它以排除cdata – user1946448