有没有办法使用MOXy从类生成XML绑定文件?

时间:2014-10-23 15:45:45

标签: jaxb moxy

我想使用MOXy来编组/解组现有类中的对象。

我想知道我的类中是否有生成XML绑定文件(因为我不想使用注释)的意思。

或者我们是否必须用我们的小手完成这一切:)?

2 个答案:

答案 0 :(得分:2)

默认情况下,JAXB / MOXy不需要指定任何元数据(请参阅:http://blog.bdoughan.com/2012/07/jaxb-no-annotations-required.html)。您只需要指定要覆盖默认行为的元数据。

我猜你真正的问题是创建MOXy外部映射文档的最简单方法是什么。我使用Eclipse执行以下操作,您最喜欢的IDE可能有类似的步骤:

  1. 获取MOXy映射文档的XML Schema

    <EclipseLink_Home>/xsds/eclipselink_oxm_2_5.xsd
    
  2. 在IDE中注册XML Schema

    1. Eclipse |偏好| XML | XML目录|添加
  3. 在IDE中创建和XML文档,并将以下内容指定为根元素。

    <xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"/>
    
  4. 使用IDE提供的自动完成功能构建XML文档。

答案 1 :(得分:1)

另一种选择是生成jaxb类,并从那些读取绑定(注释)生成外部映射(之后可以删除注释)。 PoC代码:

    public class MoxyBindingGenerator {
    private static final String PACKAGE = "com.company.binding.jaxbclasses";
    private static ObjectFactory xmlBindingsFactory = new ObjectFactory();

    public static void main(String[] args) throws Exception {
        Collection<TypeInfo> typeInfos = readAnnotations();

        XmlBindings xmlBindings = xmlBindingsFactory.createXmlBindings();
        xmlBindings.setPackageName(PACKAGE);

        JavaTypes javaTypes = xmlBindingsFactory.createXmlBindingsJavaTypes();
        xmlBindings.setJavaTypes(javaTypes);
        List<JavaType> javaTypesList = javaTypes.getJavaType();

        XmlEnums xmlEnums = xmlBindingsFactory.createXmlBindingsXmlEnums();
        xmlBindings.setXmlEnums(xmlEnums);
        List<XmlEnum> xmlEnumsList = xmlEnums.getXmlEnum();

        typeInfos.stream().forEach(typeInfo -> {
            if (!typeInfo.isEnumerationType()) {
                fillJavaTypes(javaTypesList, typeInfo);
            }
            else {
                fillEnumTypes(xmlEnumsList, typeInfo);
            }
        });

        saveToFile(xmlBindings);
    }

    private static Collection<TypeInfo> readAnnotations() throws JAXBException, Exception {
        JAXBContext jaxbContext = (JAXBContext) javax.xml.bind.JAXBContext.newInstance(PACKAGE);
        Object contextState = getPrivateField(jaxbContext, "contextState");
        Generator generator = (Generator) getPrivateField(contextState, "generator");
        AnnotationsProcessor annotationsProcessor = generator.getAnnotationsProcessor();
        Collection<TypeInfo> typeInfos = annotationsProcessor.getTypeInfo().values();
        return typeInfos;
    }

    private static void fillEnumTypes(List<XmlEnum> xmlEnumsList, TypeInfo typeInfo) {
        EnumTypeInfo et = (EnumTypeInfo) typeInfo;

        XmlEnum xmlEnum = xmlBindingsFactory.createXmlEnum();
        xmlEnum.setJavaEnum(et.getJavaClassName());
        List<String> xmlEnumNames = et.getFieldNames();
        List<Object> xmlEnumValues = et.getXmlEnumValues();
        for (int i = 0; i < xmlEnumNames.size(); i++) {
            String xmlEnumName = xmlEnumNames.get(i);
            Object xmlEnumObject = xmlEnumValues.get(i);

            XmlEnumValue xmlEnumValue = xmlBindingsFactory.createXmlEnumValue();
            xmlEnumValue.setJavaEnumValue(xmlEnumName);
            xmlEnumValue.setValue(xmlEnumObject.toString());
            xmlEnum.getXmlEnumValue().add(xmlEnumValue);
        }
        xmlEnumsList.add(xmlEnum);
    }

    private static void fillJavaTypes(List<JavaType> javaTypesList, TypeInfo typeInfo) {
        JavaType javaType = xmlBindingsFactory.createJavaType();
        javaType.setName(typeInfo.getJavaClassName());
        fillXmlType(javaType, typeInfo);
        if (typeInfo.getXmlRootElement() != null) {
            XmlRootElement xmlRootElement = typeInfo.getXmlRootElement();
            xmlRootElement.setNamespace(null);
            javaType.setXmlRootElement(xmlRootElement);
        }
        JavaAttributes javaAttributes = xmlBindingsFactory.createJavaTypeJavaAttributes();
        javaType.setJavaAttributes(javaAttributes);
        List<JAXBElement<? extends JavaAttribute>> javaAttributeList = javaAttributes.getJavaAttribute();
        typeInfo.getNonTransientPropertiesInPropOrder().stream().forEach(field -> {
            fillFields(javaAttributeList, field);
        });
        javaTypesList.add(javaType);
    }

    private static void fillFields(List<JAXBElement<? extends JavaAttribute>> javaAttributeList, Property field) {
        if (field.getXmlElements() != null && field.getXmlElements().getXmlElement().size() > 0) {
            XmlElements xmlElements = xmlBindingsFactory.createXmlElements();
            xmlElements.setJavaAttribute(field.getPropertyName());
            List<XmlElement> elements = field.getXmlElements().getXmlElement();
            elements.stream().forEach(e -> {
                e.setDefaultValue(null);
                e.setNamespace(null);
                xmlElements.getXmlElement().add(e);
            });
            JAXBElement<XmlElements> value = xmlBindingsFactory.createXmlElements(xmlElements);
            javaAttributeList.add(value);
        }
        else if (!field.isAttribute()) {
            XmlElement value = xmlBindingsFactory.createXmlElement();
            value.setJavaAttribute(field.getPropertyName());
            value.setName(field.getSchemaName().getLocalPart());
            if (field.isNillable())
                value.setNillable(field.isNillable());
            if (field.isRequired())
                value.setRequired(field.isRequired());
            javaAttributeList.add(xmlBindingsFactory.createXmlElement(value));
        }
        else {
            XmlAttribute value = xmlBindingsFactory.createXmlAttribute();
            value.setJavaAttribute(field.getPropertyName());
            value.setName(field.getSchemaName().getLocalPart());
            javaAttributeList.add(xmlBindingsFactory.createXmlAttribute(value));
        }
    }

    private static void saveToFile(XmlBindings xmlBindings)
            throws JAXBException, PropertyException, FileNotFoundException, IOException {
        JAXBContext xmlModelJaxbContext =
            (JAXBContext) javax.xml.bind.JAXBContext.newInstance("org.eclipse.persistence.jaxb.xmlmodel");
        JAXBMarshaller marshaller = xmlModelJaxbContext.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        FileOutputStream fos = new FileOutputStream(new File(System.getProperty("user.home"), "binding-imspoor-oxm.xml"));
        marshaller.marshal(xmlBindings, fos);
        fos.close();
    }

    private static void fillXmlType(JavaType javaType, TypeInfo typeInfo) {
        XmlType orgXmlType = typeInfo.getXmlType();
        if (orgXmlType != null) {
            boolean add = false;
            XmlType xmlType = xmlBindingsFactory.createXmlType();
            if (!StringUtils.isEmpty(orgXmlType.getName())) {
                xmlType.setName(orgXmlType.getName());
                add = true;
            }
            if (orgXmlType.getPropOrder() != null && orgXmlType.getPropOrder().size() > 1) {
                xmlType.getPropOrder().addAll(orgXmlType.getPropOrder());
                add = true;
            }
            if (add)
                javaType.setXmlType(xmlType);
        }
    }

    private static Object getPrivateField(Object obj, String fieldName) throws Exception {
        Field declaredField = obj.getClass().getDeclaredField(fieldName);
        declaredField.setAccessible(true);
        return declaredField.get(obj);
    }
}