栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

JAXB-将动态生成的名称空间移动到文档根目录

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JAXB-将动态生成的名称空间移动到文档根目录

我的建议

我的建议是让JAXB实现根据需要编写名称空间声明。只要元素正确地通过名称空间限定,名称空间声明出现的位置就没有关系。

如果您忽略我的建议,则可以使用以下方法。


原始答案

指定要包含在根元素上的命名空间

您可以使用

NamespacePrefixMapper
扩展将额外的名称空间声明添加到根元素(请参阅:https
:
//jaxb.java.net/nonav/2.2.11/docs/ch05.html#prefixmapper)。您将需要从您自己的对象模型中派生应在根目录中声明哪些名称空间。

注意:

NamespacePrefixMapper
com.sun.xml.bind.marshaller
包装中。这意味着您将在类路径上需要JAXB参考实现罐(请参阅:https
://jaxb.java.net/ )。

import com.sun.xml.bind.marshaller.*;public class MyNamespacePrefixMapper extends NamespacePrefixMapper {    @Override    public String getPreferredPrefix(String arg0, String arg1, boolean arg2) {        return null;    }    @Override    public String[] getPreDeclaredNamespaceUris2() {        return new String[] {"ns1", "http://www.example.com/FOO", "ns2", "http://www.example.com/BAR"};    }}

NamespacePrefixMapper
上指定
Marshaller

com.sun.xml.bind.namespacePrefixMapper
属性用于指定
NamespacePrefixMapper
Marshaller

marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new MyNamespacePrefixMapper());

示范代码

Java模型(Foo)

import javax.xml.bind.annotation.*;@XmlRootElementpublic class Foo {    private Object object;    @XmlAnyElement    public Object getObject() {        return object;    }    public void setObject(Object object) {        this.object = object;    }}

演示版

import javax.xml.bind.*;import javax.xml.parsers.*;import org.w3c.dom.*;import org.w3c.dom.Element;public class Demo {    public static void main(String[] args) throws Exception {        JAXBContext jc = JAXBContext.newInstance(Foo.class);        Foo foo = new Foo();        documentBuilderFactory dbf = documentBuilderFactory.newInstance();        documentBuilder db = dbf.newdocumentBuilder();        document document = db.newdocument();        Element element = document.createElementNS("http://www.example.com/FOO", "ns1:foo");        foo.setObject(element);        Marshaller marshaller = jc.createMarshaller();        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);        marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new MyNamespacePrefixMapper());        marshaller.marshal(foo, System.out);    }}

输出量

以下是将产生的示例输出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><foo xmlns:ns1="http://www.example.com/FOO" xmlns:ns2="http://www.example.com/BAR">    <ns1:foo/></foo>

更新

明确的答案,谢谢。但是,我需要从SimpleElementAdapter访问NSMapper。你有什么建议?我现在看到的唯一方法是使NSMapper成为可变的单例,以便SimpleElementAdapter可以根据需要添加名称空间。

我忘了你

XmlAdapter

Java模型

下面是该模型的一个更复杂的迭代,其中不

Foo
持有DOM元素的实例,而是持有DOM的实例,并将其实例
Bar
改编为DOM元素的实例。

oo

import javax.xml.bind.annotation.*;import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;@XmlRootElementpublic class Foo {    private Bar bar;    @XmlAnyElement    @XmlJavaTypeAdapter(BarAdapter.class)    public Bar getBar() {        return bar;    }    public void setBar(Bar bar) {        this.bar = bar;    }}

酒吧

public class Bar {    private String value;    public String getValue() {        return value;    }    public void setValue(String value) {        this.value = value;    }}

酒吧适配器

import javax.xml.bind.annotation.adapters.XmlAdapter;import javax.xml.parsers.*;import org.w3c.dom.*;public class BarAdapter extends XmlAdapter<Object, Bar>{    @Override    public Object marshal(Bar bar) throws Exception {        documentBuilderFactory dbf = documentBuilderFactory.newInstance();        documentBuilder db = dbf.newdocumentBuilder();        document document = db.newdocument();        Element element = document.createElementNS("http://www.example.com/BAR", "ns:bar");        element.setTextContent(bar.getValue());        return element;    }    @Override    public Bar unmarshal(Object arg0) throws Exception {        // TODO Auto-generated method stub        return null;    }}

抓取命名空间声明

由于您的对象模型不直接保存DOM元素,因此您无法遍历它来获取名称空间声明。相反,我们可以委托元帅

ContentHandler
来收集它们。以下是编组至的原因
ContentHandler

  1. 它为我们提供了一个简单的事件,可用于收集名称空间声明。
  2. 它实际上不产生任何东西,因此它是我们可以使用的最轻的元帅目标。

    NsContentHandler contentHandler = new NsContentHandler();
    marshaller.marshal(foo, contentHandler);

NsContentHandler

的实现

ContentHandler
将类似于:

import java.util.*;import org.xml.sax.SAXException;import org.xml.sax.helpers.DefaultHandler;public class NsContentHandler extends DefaultHandler {    private Map<String, String> namespaces = new TreeMap<String, String>();    @Override    public void startPrefixMapping(String prefix, String uri) throws SAXException {        if(!namespaces.containsKey(prefix)) { namespaces.put(prefix, uri);        }    }    public Map<String, String> getNamespaces() {        return namespaces;    }}

指定要包含在根元素上的命名空间

MyNamespacePrefixMapper
更改的实现可以使用从我们的捕获的namrespaces
ContentHandler

import java.util.Map;import java.util.Map.Entry;import com.sun.xml.bind.marshaller.*;public class MyNamespacePrefixMapper extends NamespacePrefixMapper {    private String[] namespaces;    public MyNamespacePrefixMapper(Map<String, String> namespaces) {        this.namespaces = new String[namespaces.size() * 2];        int index = 0;        for(Entry<String, String> entry : namespaces.entrySet()) { this.namespaces[index++] = entry.getKey(); this.namespaces[index++] = entry.getValue();        }    }    @Override    public String getPreferredPrefix(String arg0, String arg1, boolean arg2) {        return null;    }    @Override    public String[] getPreDeclaredNamespaceUris2() {        return namespaces;    }}

示范代码

import javax.xml.bind.*;public class Demo {    public static void main(String[] args) throws Exception {        JAXBContext jc = JAXBContext.newInstance(Foo.class);        Bar bar = new Bar();        bar.setValue("Hello World");        Foo foo = new Foo();        foo.setBar(bar);        Marshaller marshaller = jc.createMarshaller();        // Marshal First Time to Get Namespace Declarations        NsContentHandler contentHandler = new NsContentHandler();        marshaller.marshal(foo, contentHandler);        // Marshal Second Time for Real        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);        marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new MyNamespacePrefixMapper(contentHandler.getNamespaces()));        marshaller.marshal(foo, System.out);    }}

输出量

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><foo xmlns:ns="http://www.example.com/BAR">    <ns:bar>Hello World</ns:bar></foo>


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/464112.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号