我们正在使用JAXB解组一个看起来有点像这样的XML片段:
<someRandomElement xmlns:foo="http://example.com/foo" xpath="//foo:bar" />
我们的对象模型是:
@XmlRootElement(name="someRandomElement")
class SomeRandomClass {
@XmlAttribute(name="xpath")
private XPathFragment _expression;
}
class XPathFragment {
String _expr;
// we need this to look up namespace prefixes used in _expr
Node _parentNode;
}
所以我的问题是,如何使用JAXB从XML解组XPathFragment?
我尝试过为XPathFragment使用自定义XmlAdapter,但是这似乎没有机会访问与someRandomElement及其属性相对应的DOM节点。
答案 0 :(得分:2)
您可以利用将初始化的XmlAdapter传递给unmarshaller的功能。
<强> XPathFragmentAdapter 强>
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.w3c.dom.Document;
public class XPathFragmentAdapter extends XmlAdapter<String, XPathFragment>{
private Document document;
public XPathFragmentAdapter() {
}
public XPathFragmentAdapter(Document document) {
this.document = document;
}
@Override
public XPathFragment unmarshal(String v) throws Exception {
XPathFragment xPathFragment = new XPathFragment();
xPathFragment.set_expr(v);
xPathFragment.set_parentNode(document.getDocumentElement());
return xPathFragment;
}
@Override
public String marshal(XPathFragment v) throws Exception {
return v.get_expr();
}
}
<强>演示强>
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
public class Demo {
public static void main(String[] args) throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
File file = new File("input.xml");
Document document = db.parse(file);
JAXBContext jc = JAXBContext.newInstance(SomeRandomClass.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setAdapter(new XPathFragmentAdapter(document));
SomeRandomClass src = (SomeRandomClass) unmarshaller.unmarshal(document);
System.out.println(src.get_expression().get_parentNode() != null);
}
}
<强> SomeRandomClass 强>
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement(name="someRandomElement")
class SomeRandomClass {
private XPathFragment _expression;
@XmlAttribute(name="xpath")
@XmlJavaTypeAdapter(XPathFragmentAdapter.class)
public XPathFragment get_expression() {
return _expression;
}
public void set_expression(XPathFragment _expression) {
this._expression = _expression;
}
}
<强> XPathFragment 强>
import javax.xml.bind.annotation.XmlTransient;
import org.w3c.dom.Node;
class XPathFragment {
String _expr;
// we need this to look up namespace prefixes used in _expr
Node _parentNode;
public String get_expr() {
return _expr;
}
public void set_expr(String _expr) {
this._expr = _expr;
}
@XmlTransient
public Node get_parentNode() {
return _parentNode;
}
public void set_parentNode(Node _parentNode) {
this._parentNode = _parentNode;
}
}
答案 1 :(得分:0)
对于JAXB RI:
为您的XmlAdapter
撰写自定义XPathFragment
。您可以通过UnmarshallingContext.getInstance()
在解组期间访问当前的命名空间上下文。了解如何实现QName
处理(检查com.sun.xml.bind.v2.model.runtime.RuntimeBuiltinLeafInfo
的实现)。解析QName也需要命名空间解析,就像你XPathFragment
case。