处理 JAXB 枚举键名
Manipulate JAXB enum key names
最近几天我一直在为我的 jaxb 问题寻找解决方案,但没有成功...所以我希望这里有人可以帮助我。
基础是来自外部合作伙伴的 xsd 架构,它是原样的,即我无法更改它。 classes 是用 xjc 生成的,没有问题,但枚举不是 "java compatible"。
有些值是数字或字母数字,因此必须在绑定中设置属性 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"),
//...
}
我找到的唯一解决方案是为绑定中的每个枚举值定义枚举键。但问题是,这大约有 14.000 个值!
那么有没有人有其他想法来解决这个问题?当 xjc 生成 classes 时,是否可以为 override/change 枚举值定义一个方法?或者使用 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>
可以用模板调用替换简单的文档 "dump",模板调用可以处理文本,或提供替代方案,或针对特定条件发出消息等。
生成的输出可能如下所示:
<?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>
最近几天我一直在为我的 jaxb 问题寻找解决方案,但没有成功...所以我希望这里有人可以帮助我。
基础是来自外部合作伙伴的 xsd 架构,它是原样的,即我无法更改它。 classes 是用 xjc 生成的,没有问题,但枚举不是 "java compatible"。 有些值是数字或字母数字,因此必须在绑定中设置属性 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"),
//...
}
我找到的唯一解决方案是为绑定中的每个枚举值定义枚举键。但问题是,这大约有 14.000 个值! 那么有没有人有其他想法来解决这个问题?当 xjc 生成 classes 时,是否可以为 override/change 枚举值定义一个方法?或者使用 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>
可以用模板调用替换简单的文档 "dump",模板调用可以处理文本,或提供替代方案,或针对特定条件发出消息等。
生成的输出可能如下所示:
<?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>