开发者

Is it possible to get the DOM Attr for an attribute using JAXB?

We're using JAXB to unmarshall a fragment of XML which looks a bit like this:

<someRandomElement xmlns:foo="http://example.com/foo" xpath="//foo:bar" />

Our object model is:

@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;
}

So my question is, how can I unmarshall the XPathFragment from the XML using JAXB?

I have tried using a custom XmlAdapter for XPathFragment, but this doesn't seem to have an opportunity to access the DOM Nodes corresponding to the someRandomElement and its attributes.


You could leverage the ability to pass an initialized XmlAdapter to an 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();
    }

}

Demo

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;
    }

}


For JAXB RI:

Write a custom XmlAdapter for your XPathFragment. You can access the current namespace context during unmarshalling via UnmarshallingContext.getInstance(). See how QName handling is implemented (check implementations of com.sun.xml.bind.v2.model.runtime.RuntimeBuiltinLeafInfo). Parsing of QName also needs namespace resolution, just like you XPathFragment case.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜