java - 用于多个包的 MOXy XmlNameTransformer

标签 java xml jaxb marshalling moxy

我正在尝试使用 MOXy 为跨多个包的类自定义 XML 编码和架构生成的命名算法。

我正在关注 Eclipse documentation并可以让它为单个类工作:

@XmlNameTransformer(com.example.test.NameGenerator.class)
public class Customer

或单个包:

@XmlNameTransformer(com.example.test.NameGenerator.class)
package com.example.test;

(外部绑定(bind)文件也可以使用,但同样,您只能为每个绑定(bind)文件指定包)

但是,由于我的对象跨越多个包,所以我不想为每个包定义转换器。另外,我想动态地执行此操作(即,直到运行时才知道各个包)。

我尝试在父包 (com.example) 中定义转换器,但这不起作用 - 看起来它需要是带注释的类所在的确切包。

有什么想法吗?

更新 - 更多信息

也许我应该提到我尝试这样做的主要原因,以便我可以控制 XML/XSD 生成 - 最具体地说,我希望复杂类型为大写而不是默认的小写(不需要注释每个类),例如

@XmlRootElement
public class Test ...

应该生成:

<Test>
...
</Test>

而不是

<test>
...
</test>

根据我所做的其他研究,我发现实现此目的的唯一方法是使用 XmlNameTransformer。但如果有另一种方法,而我找错了树……一定要让我知道!

最佳答案

扩展 Blaise 的答案,这是我的实现的样子。这通过使用一组动态包的转换器来实现。

import org.eclipse.persistence.jaxb.metadata.MetadataSourceAdapter;
import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings;
import org.eclipse.persistence.jaxb.xmlmodel.XmlSchema;

public class NameTransformerAdapter extends MetadataSourceAdapter {

    private XmlBindings bindings;

    /**
     * @param packageName Fully qualified package name, like {@code com.example.test}
     */
    public NameTransformerAdapter(String packageName) {
            bindings = new XmlBindings();
            bindings.setPackageName(packageName);
            bindings.setXmlNameTransformer(XmlNameTransformer.class.getName());
            bindings.setXmlSchema(new XmlSchema()); // this is necessary
    }
    @Override
    public XmlBindings getXmlBindings(Map<String, ?> properties, ClassLoader classLoader) {
            return bindings;
    }
}

引用的变压器非常简单:

import org.eclipse.persistence.oxm.XMLNameTransformer;

public class XmlNameTransformer implements XMLNameTransformer {

    /** Uses capitalized name of class */
    public String transformTypeName(String name) {
            return name.substring(name.lastIndexOf('.') + 1);
    }
    public String transformElementName(String name) {
            return name;
    }
    public String transformAttributeName(String name) {
            return name;
    }
    public String transformRootElementName(String name) {
            return transformTypeName(name);
    }
}

包在运行时确定并按如下方式进行跟踪:

List<MetadataSource> adapters = new ArrayList<MetadataSource>();
adapters.add(new NameTransformerAdapter(packageName));

最后,可以使用上述适配器获取 JAXBContext:

import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.jaxb.JAXBContextProperties;

private JAXBContext getContext(Class<?>[] classes) throws JAXBException {
    Map<String, Object> properties = new HashMap<String, Object>();
    properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, adapters);
    return JAXBContextFactory.createContext(classes, properties);
}

关于java - 用于多个包的 MOXy XmlNameTransformer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22461952/

相关文章:

java - SWI Prolog Java jpl.PrologException 查询不起作用

java - 字符串内子字符串的计数

java - 我该如何调试这个 NullPointerException

java - JAXB 模式与类/包的关系

java - 从 Java 6 升级到 Java 7 时 native 堆上出现 OutOfMemoryError

java - 将 ID 列表与其对应的对象进行匹配

java - 如何在java中编写偶数或奇数程序?

java - 使用 Java 转换 XML 有哪些不同的方法?

java - 如何将一个xml元素绑定(bind)到一个对象成员变量中?

xml - XPath:通过非父选择器寻址值