docx4j 3.3.0高效深拷贝使用下面的代码来克隆一个JAXB对象:莫西:JAXBElement的
public static <T> T deepCopy(T value, JAXBContext jc) {
if (value==null) {
throw new IllegalArgumentException("Can't clone a null argument");
}
try {
@SuppressWarnings("unchecked")
Class<T> clazz = (Class<T>) value.getClass();
JAXBElement<T> contentObject = new JAXBElement<T>(new QName(clazz.getSimpleName()), clazz, value);
JAXBSource source = new JAXBSource(jc, contentObject);
JAXBElement<T> elem = jc.createUnmarshaller().unmarshal(source, clazz);
T res;
if (value instanceof JAXBElement<?>) {
@SuppressWarnings("unchecked")
T resT = (T) elem;
res = resT;
} else {
@SuppressWarnings("unchecked")
T resT = (T) elem.getValue();
res = resT;
}
return res;
} catch (JAXBException ex) {
throw new IllegalArgumentException(ex);
}
}
随着莫西V2.5.2(我们使用,因为它支持Java 6)和最新的2.6.3,试图克隆的JAXBElement,例如:
public void testIssue212() {
CTBookmark bookmark = Context.getWmlObjectFactory().createCTBookmark();
JAXBElement<CTBookmark> el =Context.getWmlObjectFactory().createBodyBookmarkStart(bookmark);
Object o = XmlUtils.deepCopy(el);
}
结果:
[Exception [EclipseLink-25007] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A descriptor for class javax.xml.bind.JAXBElement was not found in the project. For JAXB, if the JAXBContext was bootstrapped using TypeMappingInfo[] you must call a marshal method that accepts TypeMappingInfo as an input parameter.]
at org.eclipse.persistence.jaxb.JAXBUnmarshaller.handleXMLMarshalException(JAXBUnmarshaller.java:980)
at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:303)
at org.docx4j.XmlUtils.deepCopy(XmlUtils.java:974)
... 25 more
Caused by: Exception [EclipseLink-25007] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A descriptor for class javax.xml.bind.JAXBElement was not found in the project. For JAXB, if the JAXBContext was bootstrapped using TypeMappingInfo[] you must call a marshal method that accepts TypeMappingInfo as an input parameter.
at org.eclipse.persistence.exceptions.XMLMarshalException.descriptorNotFoundInProject(XMLMarshalException.java:140)
at org.eclipse.persistence.internal.oxm.Context$ContextState.getSession(Context.java:145)
at org.eclipse.persistence.oxm.XMLContext$XMLContextState.getSession(XMLContext.java:795)
at org.eclipse.persistence.oxm.XMLContext$XMLContextState.getSession(XMLContext.java:1)
at org.eclipse.persistence.internal.oxm.Context.getSession(Context.java:466)
at org.eclipse.persistence.oxm.XMLContext.getSession(XMLContext.java:364)
at org.eclipse.persistence.oxm.XMLContext.getSession(XMLContext.java:1)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:466)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:695)
at org.eclipse.persistence.oxm.XMLUnmarshaller.unmarshal(XMLUnmarshaller.java:655)
at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:301)
... 26 more
我们可以解决这个机智像这样的东西:
JAXBElement<T> elem;
if (Context.getJaxbImplementation().equals(JAXBImplementation.ECLIPSELINK_MOXy)
&& value instanceof JAXBElement<?>) {
elem = (JAXBElement<T>) value;
Class<?> valueClass = elem.getDeclaredType();
Marshaller mar = jc.createMarshaller();
ByteArrayOutputStream bout = new ByteArrayOutputStream(256);
mar.marshal(elem, bout);
Unmarshaller unmar = jc.createUnmarshaller();
elem = (JAXBElement<T>)unmar.unmarshal(new StreamSource(new ByteArrayInputStream(
bout.toByteArray())), valueClass);
}
但有没有更好的办法?
感谢您的支持。 iirc,我过去一直试图一次使用多个扩展。 docx4j使用父指针插件 – JasonPlutext