MOXy XmlNameTransformer for Multiple Packages

时间:2014-03-17 18:04:35

标签: 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;

(外部绑定文件也可以,但是你只能指定每个绑定文件的包)

然而,因为我有跨多个包的对象,我不想为每个包定义转换器。另外,我想动态地这样做(即直到运行时才知道各个包)。

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

有什么想法吗?

更新 - 更多信息

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

@XmlRootElement
public class Test ...

应该生成:

<Test>
...
</Test>

而不是

<test>
...
</test>

从我做过的其他研究中,我发现这样做的唯一方法是使用XmlNameTransformer。但是,如果还有另一种方式,我正在咆哮错误的树...绝对让我知道!

2 个答案:

答案 0 :(得分:1)

扩展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);
}

答案 1 :(得分:0)

包级别是您可以指定MOXy / JAXB元数据的最大范围。您可以使用XmlNameTransformer的相同实现,但是您需要为每个要应用它的包指定它。

  

但是,由于我的对象跨越多个包,我   不想为每个包定义变压器。   另外,我想动态地这样做(即个人   在运行时之前,包都不知道。

您可以以编程方式创建与外部映射文档对应的对象模型。然后,您可以在创建JAXBContext时传递此实例。