xml - 处理 JAXB 枚举键名

标签 xml enums xsd jaxb xjc

最近几天我一直在为我的 jaxb 问题寻找解决方案,但没有成功......所以我希望这里有人可以帮助我。

基础是来自外部合作伙伴的 xsd 架构,它是原样的,即我无法更改它。这些类是用 xjc 生成的,没有问题,但枚举不是“java 兼容的”。 有些值是数字或字母数字,因此必须在绑定(bind)中设置属性 typesafeEnumMemberName="generateName"。

然后 Jaxb 生成枚举键,如 VALUE_1、VALUE_2 等。我现在的问题是,一些枚举有 < 250 个条目,只有条目的 javadoc 说明了有关值的信息。 这不是很舒服,并且会导致错误,因为以下 MandatType 枚举的值 VALUE_1 的值为“E”而不是“1”...... xsd:

<xsd:simpleType name="MandatType">
    <xsd:annotation>
        <xsd:documentation/>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
        <xsd:maxLength value="1"/>
        <xsd:minLength value="1"/>
        <xsd:enumeration value="E">
            <xsd:annotation>
                <xsd:documentation>Erinnerung</xsd:documentation>
            </xsd:annotation>
        </xsd:enumeration>
        <xsd:enumeration value="1">
            <xsd:annotation>
                <xsd:documentation>Klage</xsd:documentation>
            </xsd:annotation>
        </xsd:enumeration>
        <xsd:enumeration value="2">
            <xsd:annotation>
                <xsd:documentation>Beschaffung</xsd:documentation>
            </xsd:annotation>
        </xsd:enumeration>
        <xsd:enumeration value="Z">
            <xsd:annotation>
                <xsd:documentation>Storno</xsd:documentation>
             </xsd:annotation>
        </xsd:enumeration>
    </xsd:restriction>
</xsd:simpleType>

类(class):

@XmlType(name = "MandatType")
@XmlEnum
public enum MandatType {
    /**
     * Erinnerung 
     * 
     */
    @XmlEnumValue("E")
    VALUE_1("E"),

    /**
     * Klage
     * 
     */
    @XmlEnumValue("1")
    VALUE_2("1"),

    /**
     * Beschaffung
     * 
     */
    @XmlEnumValue("2")
    VALUE_3("2"),

    /**
     * Storno
     * 
     */
    @XmlEnumValue("Z")
    VALUE_Z("Z"),

    //...
}

我找到的唯一解决方案是为绑定(bind)中的每个枚举值定义枚举键。但问题是,这大约有 14.000 个值! 那么有没有人有其他想法来解决这个问题?是否可以定义一种方法来在 xjc 生成类时覆盖/更改枚举值?或者使用 xsd:documentation 值作为枚举的键?

非常感谢 斯蒂芬

最佳答案

可以编写您自己的 JAXB 插件,然后可以使用该插件合并任意数据以修改生成的代码。这link有一些提示,您可以探索这些提示以获取更多信息。

或者,您可能会考虑更简单的方法(在我看来),那就是将您的 XSD 重构为可以使用开箱即用功能的东西。

如果你想要的只是沿着这些路线,转换它:

    <xsd:enumeration value="E">
        <xsd:annotation>
            <xsd:documentation>Erinnerung</xsd:documentation>
        </xsd:annotation>
    </xsd:enumeration>

进入这个:

    <xsd:enumeration value="E">
        <xsd:annotation>
            <xsd:documentation>Erinnerung</xsd:documentation>
            <xsd:appinfo>
                <jaxb:typesafeEnumMember name="Erinnerung"/>
            </xsd:appinfo>              
        </xsd:annotation>
    </xsd:enumeration>

那么我认为基本的 XSLT 技能应该可以帮助您解决这个问题,这比编写 JAXB 插件或使用 XSOM 等要好。在这些情况下,14000 左右应该没什么区别。即使您的模式分布在数百个文件中,仍然可以更轻松地调整一次执行一个模式的愚蠢 XSLT,然后简单地为每个文件生成命令行...

这是一个简单的 XSLT:

<xsl:stylesheet version="1.0" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

    <xsl:template match="xsd:enumeration">
        <xsd:enumeration>
            <xsl:attribute name="value">
                <xsl:value-of select="@value"/>
            </xsl:attribute>
            <xsd:annotation>
                <xsl:copy-of select="xsd:annotation/xsd:documentation"/>
                <xsd:appinfo>
                    <jaxb:typesafeEnumMember>
                        <xsl:attribute name="name">
                             <xsl:value-of select="xsd:annotation/xsd:documentation"/>
                        </xsl:attribute>
                    </jaxb:typesafeEnumMember>
                </xsd:appinfo>                          
            </xsd:annotation>
        </xsd:enumeration>
    </xsl:template>
</xsl:stylesheet>

可以用模板调用替换简单的文档“转储”,模板调用可以处理文本,或提供替代方案,或针对特定条件发出消息等。

生成的输出可能如下所示:

<?xml version="1.0" encoding="utf-16"?>
<xsd:schema targetNamespace="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns="http://tempuri.org/XMLSchema.xsd" xmlns:xtm="http://paschidev.com/schemas/metadata/xtm">
    <xsd:simpleType name="MandatType">
        <xsd:annotation>
            <xsd:documentation/>
        </xsd:annotation>
        <xsd:restriction base="xsd:string">
            <xsd:maxLength value="1"/>
            <xsd:minLength value="1"/>
            <xsd:enumeration value="E">
                <xsd:annotation>
                    <xsd:documentation>Erinnerung</xsd:documentation>
                    <xsd:appinfo>
                        <jaxb:typesafeEnumMember name="Erinnerung"/>
                    </xsd:appinfo>
                </xsd:annotation>
            </xsd:enumeration>
            <xsd:enumeration value="1">
                <xsd:annotation>
                    <xsd:documentation>Klage</xsd:documentation>
                    <xsd:appinfo>
                        <jaxb:typesafeEnumMember name="Klage"/>
                    </xsd:appinfo>
                </xsd:annotation>
            </xsd:enumeration>
            <xsd:enumeration value="2">
                <xsd:annotation>
                    <xsd:documentation>Beschaffung</xsd:documentation>
                    <xsd:appinfo>
                        <jaxb:typesafeEnumMember name="Beschaffung"/>
                    </xsd:appinfo>
                </xsd:annotation>
            </xsd:enumeration>
            <xsd:enumeration value="Z">
                <xsd:annotation>
                    <xsd:documentation>Storno</xsd:documentation>
                    <xsd:appinfo>
                        <jaxb:typesafeEnumMember name="Storno"/>
                    </xsd:appinfo>
                </xsd:annotation>
            </xsd:enumeration>
        </xsd:restriction>
    </xsd:simpleType>
</xsd:schema>

关于xml - 处理 JAXB 枚举键名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32786230/

相关文章:

xml - ClassNotFoundException : org. apache.xml.serializer.TreeWalker

java - JAXB 将 XML 片段映射为另一个 XML 文档中的片段

c++ - 资源编译器无法编译 Win32 资源脚本中的枚举语句?

jenkins - Jenkins 中的作业有 xsd 或 xml 模式吗?

xml - 错误 "The element cannot contain white space. Content model is empty."是什么意思?

java - 特定字段的可空属性值的 Jaxb 自定义

java - Eclipse 电子邮件 + 图片

java - 如何加载 N-Triples 模型并从 RDF 文件中获取 namespace ?(新手)

nhibernate - 为什么Fluent NHibernate不理会我的约定?

c# - 从枚举中存储和读取附加信息的有效方法是什么