jaxb - 如何在 JAXB Unmarshal 中持久化 Element 的 UserData?
问题描述
我将文档解组为对象,如下所示。在此之前,在解析 XML 时,使用 setUserData 来存储每个元素的位置信息。
class MyJaxbAdapter extends XmlAdapter<Object, SubObject> {}
@Override
public UnattendComponent unmarshal(Object v) throws Exception {
Node node = (Node) v; // ElementNSImpl; It's probably a newly created object. Because It is different from the document object given by ownerDocument as SAXSource.
node.getUserData(...) // return NULL
}
}
Document document = ...;
unmarshaller.setAdapter(new MyJaxbAdapter());
MyXMLObject object = unmarshaller.unmarshal(new DOMSource(document), MyXMLObject.class).getValue();
但我无法在 XmlAdapter 的解组方法中获取 UserData。有没有办法持久化 UserData?
定位器信息存储在 Element 的属性中,如下所示。
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
Element el = document.createElementNS(usedNamespaceUri, qName);
// ...
el.setUserData(
ElementUserData.class.getName(),
ElementUserData.builder()
.lineNumber(locator.getLineNumber())
.columnNumber(locator.getColumnNumber())
.build(),
null);
}
我需要上述代码在 XmlAdapter 的解组中存储的定位器信息(UserData)。但是,node
作为参数传递给 unmarshal 的用户数据中没有用户数据。
示例代码:
解决方案
不完全确定这是否是您正在寻找的东西,但将其作为参考提供,这样您可能会有一些想法进一步进行:
示例 XML:
<root>
<name>Batman</name>
<year>2008</year>
</root>
根类:
@XmlRootElement(name = "root")
@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
private String name;
private String year;
@XmlJavaTypeAdapter(CustomAdapter.class)
private String after;
private void afterUnmarshal(Unmarshaller m, Object parent) {
after = name;
}
}
自定义适配器类:
public class CustomAdapter extends XmlAdapter<String, String> {
@Override
public String unmarshal(String v) throws Exception {
System.out.println("Within Unmarshal : " + v);
return null;
}
@Override
public String marshal(String v) throws Exception {
System.out.println("Within Marshal : " + v);
return null;
}
}
示例主类:
public class SampleMain {
public static void main(String[] args) throws XMLStreamException, JAXBException {
final InputStream inputStream = Unmarshalling.class.getClassLoader().getResourceAsStream("sample.xml");
final XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(inputStream);
final Unmarshaller unmarshaller = JAXBContext.newInstance(Root.class).createUnmarshaller();
unmarshaller.setAdapter(new CustomAdapter());
final Root root = unmarshaller.unmarshal(xmlStreamReader, Root.class).getValue();
System.out.println(root.toString());
Marshaller marshaller = JAXBContext.newInstance(Root.class).createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(root, System.out);
}
}
输出:
Root(name=Batman, year=2008, after=Batman)
Within Marshal : Batman
<root>
<name>Batman</name>
<year>2008</year>
</root>
推荐阅读
- java - 在 Spark 中将元组转换为矩阵
- python - 如何在熊猫中将对象转换为int或float
- android - 带感叹号的 Kotlin 数据类型
- javascript - 可调用的 Firebase 函数在单击按钮时没有任何反应
- python - 试图从另一个文件导入一个类,但我的测试中断
- reactjs - 没有未使用的表达式 Reactjs 请帮助我
- c++ - 多线程 C++ winsock 套接字中重复和丢失消息的原因?
- reactjs - Prettier 在 setState 中移动 paren,触发无序列。如何改进 setState?
- javascript - 如何调用组件的 onClick 属性进行测试?
- regex - 使用 grep -P 和lookahead/lookbehind 获取模式之间的文本