Jaxb(XJC)从XML Schema(XSD)生成具有类和字段描述作为注释的类。 XJC插件

我认为许多至少一次接触过Web- Java开发人员使用了XML SchemaXSD所描述的Java DTO类的生成。 Jaxb可以应付自如 ,无论如何使用,都可以通过命令行,maven或gradle插件通过xjcwsimport调用来解决。


XSD架构生成类非常容易快捷。 但这是一个问题-原始电路中可用的描述几乎完全消失了!


实际上 ,由于只有类本身才会有Javadoc描述,因此采用固定格式(例如,您不能在没有常规的情况下将其与XML片段分开),因此完全不存在字段(字段)的描述。 而且,如果您像我一样,也需要在运行时( runtime )使用它们,那么绝对有麻烦


看起来很奇怪,必须克服这一点,该任务花费了很多时间,因此,我编写了一个插件,希望将其提供给大家,以期将来可以节省一些人的时间。


Jaxb功能一览


Jaxb历史悠久,具有良好的官方描述,包括在生成的类中添加行为


从命令行调用类生成的主要工具-xjc也没有最少的键数。 但是,对于我们的情况,不是其中之一。


当然,您不禁提及-b ,您可以在其中提供自己的绑定。 这是一种非常强大的武器,尤其是与多个插件结合使用时。 一个很好的博客文章(英文) -我建议您阅读它作为简要介绍。 但是绑定在大多数情况下限于分配的antantations或给定名称的静态值,指示要对其应用的元素。 在我的问题上这无济于事。


Jaxb(XJC)插件


在寻找现成的解决方案时,我发现了许多扩展了一代的插件。 我认为他们的审查超出了本文的范围。 重要的是,我找不到正在执行的工作。


但是,随后,在阅读http://stackoverflow.com/上的答案和问题时,我发现了一些此类问题,例如:


  1. 使用JAXB处理模式注释
  2. 如何使生成的类包含XML Schema文档中的Javadoc
  3. 如何生成一个类,可以从该类中将节点的XML检索为String

多年来,还没有一个完整的答案!


但是,回到机会这个话题,原来有一个用于编写插件的API ! 低级的,有时是令人困惑的,几乎没有文档。但是我可以说这是非常高级的,也就是说,您可以直接干预很多流程。 顺便说一下,在许多非标准情况下,通常会提到它的答案。 好吧,我试图写一个插件。


对于那些对插件编写过程的细节感兴趣的人,我可以推荐以下文章:



我想要什么,为什么


对于我们的集成之一,客户提供了带有XSD文件的档案,根据该档案,我们必须在MDM Unidata中生成模型,并与我们一起工作以进一步配置质量规则。


我注意到MDM系统本身是专有的,很多人不太可能熟悉它,但这并不重要。 最重要的是,我们必须根据XSD描述创建目录和注册表。 同时,注册表中的字段同时使用标识符(字段名称)和“显示名称”,这是俄语中人可以理解的名称。 可以使用RDBMS做出一个简单的类比(这可能也是一个有用的应用示例),在此方面我们可以假定我们想要创建数据库表,但同时为每列提供描述( comment )供以后使用。

我的计划是这样的:


  1. 使用XJC生成XSD
  2. 然后,我们使用一个漂亮的反射库并遍历所有对象,然后递归地遍历所有字段。

一切很快都适用于拉丁名称,这些名称取自field课程。 但是,俄罗斯的,易于理解的描述无处可去!


不能手动编辑描述,因为有成千上万的嵌套字段。


最初的尝试是自己为Groovy编写类似的解析器,从而破坏了XSD的描述。 总体而言,它是实施的。 但是很快就清楚了,在很多情况下需要进行额外的处理-递归调用,以restriction / extension的形式支持XSD 1.1 extension (支持继承和覆盖),不同类型的类会生成类字段,例如<element><attribute><sequence><choose>和许多其他小东西。 该实现因添加了过多的东西而长满了,但是她并没有增加和谐感。


结果,我回到了编写xjc-documentation-annotation-plugin插件的想法,我向您介绍了它,希望它对除我以外的人有用!


xjc-文档-注释-插件


一切都放在github上: https : //github.com/Hubbitus/xjc-documentation-annotation-plugin
有说明,测试和单独的- gradle使用- gradle有使用示例。


我认为从此处复制描述是没有意义的,只是简要说明一下它的作用。


假设有这样一个XSD片段:


  <xs:complexType name="Customer"> <xs:annotation> <xs:documentation></xs:documentation> </xs:annotation> <xs:sequence> <xs:element name="name" type="xs:string"> <xs:annotation> <xs:documentation>  </xs:documentation> </xs:annotation> </xs:element> </xs:sequence> </xs:complexType> 

默认情况下, XJC生成一个XJC类(为便于阅读,将省略getter,setter和一些无关的详细信息):


 /** *  * * <p>Java class for Customer complex type. * * <p>The following schema fragment specifies the expected content contained within this class. * * <pre> * &lt;complexType name="Customer"&gt; * &lt;complexContent&gt; * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType"&gt; * &lt;sequence&gt; * &lt;element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/&gt; * &lt;element name="age" type="{http://www.w3.org/2001/XMLSchema}positiveInteger"/&gt; * &lt;/sequence&gt; * &lt;/restriction&gt; * &lt;/complexContent&gt; * &lt;/complexType&gt; * </pre> * * */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "Customer", propOrder = { "name", "age" }) public class Customer { @XmlElement(required = true) protected String name; @XmlElement(required = true) @XmlSchemaType(name = "positiveInteger") protected BigInteger age; } 

使用该插件,您将获得( Javadoc保持不变,为简单起见省略):


 @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "Customer", propOrder = { "name", "age" }) @XsdInfo(name = "", xsdElementPart = "<complexType name=\"Customer\">\n <complexContent>\n <restriction base=\"{http://www.w3.org/2001/XMLSchema}anyType\">\n <sequence>\n <element name=\"name\" type=\"{http://www.w3.org/2001/XMLSchema}string\"/>\n <element name=\"age\" type=\"{http://www.w3.org/2001/XMLSchema}positiveInteger\"/>\n </sequence>\n </restriction>\n </complexContent>\n</complexType>") public class Customer { @XmlElement(required = true) @XsdInfo(name = "  ") protected String name; @XmlElement(required = true) @XmlSchemaType(name = "positiveInteger") @XsdInfo(name = "") protected BigInteger age; } 

检查添加的@XmlType批注。


这样,使用它就和其他任何注解一样简单:


  XsdInfo xsdAnnotation = CadastralBlock.class.getDeclaredAnnotation(XsdInfo.class); System.out.println("XSD description: " + xsdAnnotation.name()); 

测试中的一个有效示例: 1、2

Source: https://habr.com/ru/post/zh-CN437914/


All Articles