簡體   English   中英

JAXB - 在原始類型上忽略XmlAttribute中的'required'標記

[英]JAXB - flag 'required' from XmlAttribute being ignored on primitive types

嘗試使用JAXB庫中的schemagen工具為我的項目生成Schema時遇到了一些問題。 問題是注釋@XmlAttribute沒有被正確解析。

- src
 - teste
  - entity

因此,問題是對於某些類,由scanmagen任務完全忽略XmlAttribute required的標志。

我將在這里粘貼一些類和生成的模式的示例,以便您可以了解正在發生的事情

package teste.entity;

import javax.xml.bind.annotation.XmlAttribute;

public abstract class Class2 {

    @XmlAttribute(required=false)
    public String stringNotRequired;

    @XmlAttribute(required=true)
    public String stringRequired;

    @XmlAttribute(required=false)
    public int anotherIntNotRequired;

    @XmlAttribute(required=true)
    public int anotherIntRequired;

}

package teste.entity;

import javax.xml.bind.annotation.XmlAttribute;

public class Class1 extends Class2 {

    @XmlAttribute(required=true)
    public Integer integerRequired;

    @XmlAttribute(required=false)
    public Integer integerNotRequired;

    @XmlAttribute(required=false)
    public int intNotRequired;

    @XmlAttribute(required=true)
    public int intRequired;

    public Class1() {
    }
}

我的package-info.java

@XmlSchema(xmlns = @XmlNs(prefix = "t", namespaceURI = "http://test.com"),
namespace = "http://test.com",
elementFormDefault = XmlNsForm.UNQUALIFIED,
attributeFormDefault = XmlNsForm.UNQUALIFIED)
package teste.entity;

import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;

當我運行schemagen任務時,我得到了這個輸出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="unqualified" version="1.0" targetNamespace="http://test.com" xmlns:t="http://test.com" xmlns:tns="http://test.com" xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:complexType name="class1">
    <xs:complexContent>
      <xs:extension base="tns:class2">
        <xs:sequence/>
        <xs:attribute name="integerRequired" type="xs:int" use="required"/>
        <xs:attribute name="integerNotRequired" type="xs:int"/>
        <xs:attribute name="intNotRequired" type="xs:int" use="required"/>
        <xs:attribute name="intRequired" type="xs:int" use="required"/>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="class2" abstract="true">
    <xs:sequence/>
    <xs:attribute name="stringNotRequired" type="xs:string"/>
    <xs:attribute name="stringRequired" type="xs:string" use="required"/>
    <xs:attribute name="anotherIntNotRequired" type="xs:int" use="required"/>
    <xs:attribute name="anotherIntRequired" type="xs:int" use="required"/>
  </xs:complexType>
</xs:schema>

這是我的Ant任務

<target name="generate-schema" >
    <path id="mycp">
        <fileset dir="lib/jaxb/lib\">
            <include name="*.jar"/>
        </fileset>
        <fileset dir="lib" >
            <include name="*.jar"/>
        </fileset>
        <fileset dir="dist" >
            <include name="*.jar"/>
        </fileset>
    </path>

    <taskdef name="schemagen" classname="com.sun.tools.jxc.SchemaGenTask">
        <classpath refid="mycp"/>
    </taskdef>

    <mkdir dir="schema"/>

    <schemagen srcdir="src/teste/entity" destdir="schema" >
        <classpath refid="mycp"/>
        <schema namespace="http://test.com" file="full.xsd" />            
    </schemagen>
</target>

我是否需要在命名空間的類上進行注釋才能正確輸出?

大概。 我創建了一個類似於你的設置。

Test.java

package test;

...

@XmlType(name = "test", namespace = "http://test.com", propOrder = "b")
@XmlRootElement(name = "test", namespace = "http://test.com")
public final class Test {

  @XmlAttribute(required = false)
  public String a;

  @XmlElement
  public String b;

  public Test() {}
}

package-info.java

@XmlSchema(xmlns = @XmlNs(prefix = "tns", namespaceURI = "http://test.com"),
           namespace = "http://test.com",
           elementFormDefault = XmlNsForm.QUALIFIED,
           attributeFormDefault = XmlNsForm.QUALIFIED)
package test;

import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;

build.xml (片段,基於OP的輸入)

<schemagen srcdir="<path-to-test-package>" destdir=".">
  <classpath refid="<classpath-refid>" />
  <schema namespace="http://test.com" file="test.xsd" />
</schemagen>

test.xsd (輸出)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema 
  attributeFormDefault="qualified"
  elementFormDefault="qualified" version="1.0"
  targetNamespace="http://test.com"
  xmlns:tns="http://test.com"
  xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="test" type="tns:test"/>

  <xs:complexType name="test" final="extension restriction">
    <xs:sequence>
      <xs:element name="b" type="xs:string" minOccurs="0"/>
    </xs:sequence>
    <xs:attribute ref="tns:a"/>
  </xs:complexType>

  <xs:attribute name="a" type="xs:string"/>
</xs:schema>

(我使用了前綴tns因為JAXB將生成並使用它而不是@XmlNs中指定的任何前綴。)

鑒於上面的文件XJC的SchemaGen產生了所需的結果 - 如果我有一個必需的屬性,那么它將被生成; 如果我設置required=false ,那么它不會。

這里的主要內容是Test類上的@XmlType注釋。 如果你手工制作你的課程,你就離不開它。 @XmlRootElement不是必需的,因此如果你需要它,它取決於你的用例。)這告訴JAXB當SchemaGen處理它時, Test類(它代表一種模式類型 )屬於哪個命名空間。

package-info.java 幾乎用於相同的目的,但是在模式級別。 如果包中包含此文件(以及上面顯示的注釋)和SchemaGen遇到,那么它將知道該包中的類(模式類型)屬於包級別注釋中指定的命名空間。 (同樣,如果你手工完成這是必須的。)除此之外, SchemaGen使用此文件中聲明的命名空間將輸出發送到您在<schema namespace="http://test.com" file="test.xsd" />指定的文件<schema namespace="http://test.com" file="test.xsd" /> 沒有它,生成的文件的名稱始終是schema1.xsd (或類似的)。

多個包

如果要將位於多個包中的多個類組合到一個名稱空間中,則必須在所有包上應用相同的包級別注釋(如上面的package-info.java片段 - 使用的名稱空間前綴必須是tns ,因為前面描述的JAXB限制)。

當然需要命令schemagen來編譯這兩個包。 在你的build.xmlschemagen任務的srcdir應該包含這兩個包。

如果你有一個類似的結構

.
|-- x
|   |-- A.java             # JAXB
|   |-- B.java             # POJO
|   `-- package-info.java  # http://test.com
`-- y
    |-- C.java             # JAXB
    `-- package-info.java  # http://test.com

你可以告訴schemagen任務只編譯AC這樣的

<schemagen srcdir="." destdir="." >
  <schema namespace="http://test.com" file="test.xsd" />
  <include name="x/A.java" />
  <include name="y/C.java" />
</schemagen>

可選和必需的屬性

關於屬性的官方JAXB教程中有一個簡短的部分 ,遺憾的是,它沒有特別說明原始Java類型和XML模式類型。

您所遇到的缺點不是我認為的JAXB缺陷,而是Java 奇怪 :原始類型不能為空,這同時也是好的和壞的。

您可以通過更改原始屬性來解決此問題

@XmlAttribute
public int attribute;

@XmlAttribute
public Integer attribute;

(我找到了關於同一問題郵件列表主題 ,也許你對此感興趣。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM