是否可以使用JAXB获取属性的DOM Attr?

时间:2011-06-01 13:18:11

标签: java dom jaxb

我们正在使用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节点。

2 个答案:

答案 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。

一样