How to make generated classes contain Javadoc from XML Schema documentation

前端 未结 4 1244
太阳男子
太阳男子 2020-12-01 06:01

I\'m currently working with an XML Schema that has / on most types and elements. When I generate Jav

相关标签:
4条回答
  • I've never been able to get regular xsd:documentation to be placed in the java source except if and only if it was a Complex Type. Documentation for elements, simple types, etc are ignored.

    So, I end up using jxb:javadoc. To do so, include the definition of xmlns:jxb="http://java.sun.com/xml/ns/jaxb" in your <xsd:schema> element.

    Add a child to <xsd:complexType> or <xsd: element> or <xsd:attribute>:

    <xsd:annotation><xsd:appinfo><jxb:XXX><jxb:javadoc>
      This is my comment for a class/property
    </jxb:javadoc></jxb:XXX></xsd:appinfo></xsd:annotation>
    

    Where XXX is either "class" or "property".

    For a package you write a child to xsd:schema

    <xsd:annotation><xsd:appinfo><jxb:schemaBindings><jxb:package name="com.acme"><jxb:javadoc>
      This is my comment for a package
    </jxb:javadoc></jxb:package></jxb:schemaBindings></xsd:appinfo></xsd:annotation>
    

    Writing HTML document requires bracketing with <![CDATA[ --- ]]>

    (EDIT: While writing my answer, the question has been edited by the OP so I'm updating it accordingly)

    In my case, javadoc was the only target so it was acceptable to use jxb:javadoc. But your update makes perfect sense and, actually, I totally agree with you. Sadly, I never found an ideal solution for the situation you describe (so I'll follow this question very carefully). Maybe you could use something like xframe to generate documentation from xsd:documentation, but this doesn't answer the question.

    0 讨论(0)
  • 2020-12-01 06:48

    I find the following techniques work pretty well for adding JavaDoc headers to Java element classes (generated from XML schemas). I nest the JavaDoc in tags defined in the jax-b namespace, nested within the xml schema annotation and appinfo tags. Note the jaxb namespace defines types of documentation tags; I use two of there: the class and the property tags. defined in the following namespace: xmlns:jxb="http://java.sun.com/xml/ns/jaxb"

    1) To document a class, I use a jaxb "class" tag in the following sequence:

      <xs:complexType name="Structure">
         <xs:annotation>
            <xs:appinfo>
               <jxb:class>
                  <jxb:javadoc>
                     Documentation text goes here. Since parsing the schema  
                     into Java involves evaluating the xml, I escape all 
                     the tags I use as follows &lt;p&gt; for <p>.
                  </jxb:javadoc>
               </jxb:class>
            </xs:appinfo>
         </xs:annotation>
    
         .
         .
         .
      </xs:complexType>
    

    2) To document an element, I use the "property" tag as follows:

           <xs:element name="description" type="rep:NamedString">
              <xs:annotation>
                 <xs:appinfo>
                    <jxb:property>
                       <jxb:javadoc>
                          &lt;p&gt;Documentation goes here.&lt;/p&gt;
                       </jxb:javadoc>
                    </jxb:property>
                 </xs:appinfo>
              </xs:annotation>
           </xs:element>
    

    3) I use the same set of tags to document attributes:

          <xs:attribute name="name" type="xs:NCName" use="required">
              <xs:annotation>
                 <xs:appinfo>
                    <jxb:property>
                       <jxb:javadoc>
                          &lt;p&gt;Documentation goes here.&lt;/p&gt;
                       </jxb:javadoc>
                    </jxb:property>
                 </xs:appinfo>
              </xs:annotation>
           </xs:attribute>
    

    4) To document a choice, I use the property jaxb tag, and I document the choice.

        <xs:choice maxOccurs="unbounded">
              <xs:annotation>
                 <xs:appinfo>
                    <jxb:property>
                       <jxb:javadoc>
                          &lt;p&gt;Documentation goes here.&lt;/p&gt;
                       </jxb:javadoc>
                    </jxb:property>
                 </xs:appinfo>
              </xs:annotation>
    
              <xs:element name="value" type="rep:NamedValue" />
              <xs:element name="list" type="rep:NamedList" />
              <xs:element name="structure" type="rep:NamedStructure" />
           </xs:choice>
    

    Attempting to document the individual choices here would fail, since this tag produces an untyped list.

    0 讨论(0)
  • 2020-12-01 06:51

    Especially for that case I wrote XJC plugin xjc-documentation-annotation-plugin.

    What it does: <annotation><documentation> -> Java class annotations

    Said we have this object described in XSD:

    <xs:complexType name="CadastralBlock">
        <xs:annotation>
            <xs:documentation>Cadastral quarter</xs:documentation>
        </xs:annotation>
        <xs:sequence>
            <xs:element name="number" type="xs:string">
                <xs:annotation>
                    <xs:documentation>Cadastral number</xs:documentation>
                </xs:annotation>
            </xs:element>
    </xs:complexType>
    

    We run xjc like:

    xjc -npa -no-header -d src/main/generated-java/ -p xsd.generated scheme.xsd
    

    And got class like (getters, setters and any annotations omitted for simplicity):

    public class CadastralBlock {
        protected String number;
    }
    

    But in my case I want known how to class and fields was named in source file! So it what this plugin do!

    So you get:

    @XsdInfo(name = "Cadastral quarter", xsdElementPart = "<complexType name=\"CadastralBlock\">\n  <complexContent>\n    <restriction base=\"{http://www.w3.org/2001/XMLSchema}anyType\">\n      <sequence>\n        <element name=\"number\" type=\"{http://www.w3.org/2001/XMLSchema}string\"/></sequence>\n      </restriction>\n  </complexContent></complexType>")
    public class CadastralBlock {
        @XsdInfo(name = "Cadastral number")
        protected String number;
    }
    

    How to use

    Manual call in commandline

    If you want run it manually ensure jar class with plugin in run classpath and just add option -XPluginDescriptionAnnotation. F.e.:

    xjc -npa -no-header -d src/main/generated-java/ -p xsd.generated -XPluginDescriptionAnnotation scheme.xsd
    

    Call from Java/Groovy

    Driver.run(
        [
            '-XPluginDescriptionAnnotation'
            ,'-d', generatedClassesDir.absolutePath
            ,'-p', 'info.hubbitus.generated.test'
            ,'CadastralBlock.xsd'
        ] as String[]
        ,new XJCListener() {...}
    )
    

    See test XJCPluginDescriptionAnnotationTest for example.

    Use from Gradle

    With gradle-xjc-plugin:

    plugins {
        id 'java'
        id 'org.unbroken-dome.xjc' version '1.4.1' // https://github.com/unbroken-dome/gradle-xjc-plugin
    }
    
    ...
    
    dependencies {
        xjcClasspath 'info.hubbitus:xjc-documentation-annotation-plugin:1.0'
    }
    
    // Results by default in `build/xjc/generated-sources`
    xjcGenerate {
        source = fileTree('src/main/resources') { include '*.xsd' }
        packageLevelAnnotations = false
        targetPackage = 'info.hubbitus.xjc.plugin.example'
        extraArgs = [ '-XPluginDescriptionAnnotation' ]
    }
    

    Complete gradle example in example-project-gradle directory of project.

    0 讨论(0)
  • 2020-12-01 06:53

    This just isn't possible with the JAXB reference implementation. Even if you were to try to write an XJC plugin, you'd find that the plugin API is given no reference to the Schema definition, so there's no way to extract this information.

    Our only hope is that a future version of JAXB fixes the situation. There's an open feature request here.

    0 讨论(0)
提交回复
热议问题