2012-09-25 66 views
3

我想爲一個應用程序創建一個XSD,並且另一個XSD擴展第一個(僅通過添加元素)。XSD允許擴展,兼容性和驗證

我希望第二個應用程序生成的XML文件對第一個應用程序有效。

我嘗試這樣做:

首先XSD:

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

    <xs:complexType name="typeA"> 
    <xs:sequence> 
     <xs:element name="elA" type="xs:string" /> 
     <xs:any namespace="##any" minOccurs="0" processContents="lax" /> 
    </xs:sequence> 
    </xs:complexType> 

    <xs:element name="root" type="typeA" /> 
</xs:schema> 

二XSD:

<?xml version="1.0" encoding="UTF-8" ?> 
<xs:schema xmlns="example" 
     xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     targetNamespace="example"> 
    <xs:redefine schemaLocation="firstXSD.xsd"> 
    <xs:complexType name="typeA"> 
     <xs:complexContent> 
     <xs:extension base="typeA"> 
     <xs:sequence> 
      <xs:element name="newElement" type="xs:string" /> 
     </xs:sequence> 
     </xs:extension> 
     </xs:complexContent> 
    </xs:complexType> 
    </xs:redefine> 
</xs:schema> 

XML的實施例,其必須與第一XSD有效(但不是所述第二) :

<?xml version="1.0" encoding="UTF-8" ?> 
<root xmlns="example"> 
    <elA>MyString</elA> 
</root> 
XML的

例子必須是有效的與 XSD

<?xml version="1.0" encoding="UTF-8" ?> 
<root xmlns="example"> 
    <elA>MyString</elA> 
    <newElement>MyNewString</newElement> 
</root> 

以前的XSD違反了「唯一粒子屬性」,我想這是固定的。 我可以編輯兩個XSD,但我希望能夠在完成第二個之前分發第一個。

我該如何做到這一點(兩個模式必須有效,當由JAXB檢查)?

謝謝

回答

1

有些人可能會說:如果你可以編輯兩個XSD,爲什麼還要重新定義?

我將向您展示如何使用XSD重定義工作,至少從XSD角度來看。但是,由於JAXB的侷限性,它不適用於開箱即用。如果您還使用自動XSD重構,作爲額外的步驟,那麼您可以使其工作,並且在此過程中,您將保留使用xsd:redefine時看到的價值主張。因此,在此之前,這裏是另一種也使用組合的方式,但沒有xsd:redefine;從維護和驗證的角度來看,您正在獲得相同的價值和用法。

我將第一個XSD稱爲Model1,第二個XSD稱爲Model2。我將從一個XSD開始,它將爲您提供xs:redefine中的「通過組合重用」方面。

共同項目,XSD的允許擴展,兼容性強和驗證,共items.xsd

<?xml version="1.0" encoding="utf-8"?> 
<!--XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com)--> 
<xs:schema xmlns="example" 
     xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     targetNamespace="example" 
     elementFormDefault="qualified" attributeFormDefault="qualified"> 

    <xs:group name="typeA"> 
    <xs:sequence> 
     <xs:element name="elA" type="xs:string" /> 
    </xs:sequence> 
    </xs:group> 

    <xs:element name="root" type="typeA" /> 
</xs:schema> 

型號1「項目」,XSD的允許擴展,兼容性強,和 - 驗證,模型1項。XSD

<?xml version="1.0" encoding="utf-8"?> 
<!--XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com)--> 
<xs:schema xmlns="example" 
     xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     targetNamespace="example" 
     elementFormDefault="qualified" attributeFormDefault="qualified"> 

    <xs:complexType name="typeA"> 
    <xs:sequence> 
     <xs:group ref="typeA" /> 
     <xs:any namespace="##any" minOccurs="0" processContents="lax" /> 
    </xs:sequence> 
    </xs:complexType> 
</xs:schema> 

Model2的 「項目」,XSD的允許擴展,兼容性強和驗證,模型2-items.xsd

<?xml version="1.0" encoding="utf-8"?> 
<!--XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com)--> 
<xs:schema xmlns="example" 
     xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     targetNamespace="example" 
     elementFormDefault="qualified" attributeFormDefault="qualified"> 

    <xs:complexType name="typeA"> 
    <xs:sequence> 
     <xs:group ref="typeA" /> 
     <xs:element name="newElement" type="xs:string" /> 
    </xs:sequence> 
    </xs:complexType> 
</xs:schema> 

如果你通過通用項目和型號1,或通用項目和Model2到JAXB編譯器,它將以您想要的方式創建類。爲了方便使用(測試)和插圖,我創建了兩個以上的XSD:

型號1:

<?xml version="1.0" encoding="utf-8"?> 
<!--XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com)--> 
<xs:schema xmlns="example" 
     xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     targetNamespace="example" 
     elementFormDefault="qualified" attributeFormDefault="qualified"> 
    <xs:include schemaLocation="xsd-allow-extension-compatibility-and-validation-common-items.xsd"/> 
    <xs:include schemaLocation="xsd-allow-extension-compatibility-and-validation-model1-items.xsd"/> 
</xs:schema> 

模型2:

<?xml version="1.0" encoding="utf-8"?> 
<!--XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com)--> 
<xs:schema xmlns="example" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="example" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xs:include schemaLocation="xsd-allow-extension-compatibility-and-validation-common-items.xsd"/> 
    <xs:include schemaLocation="xsd-allow-extension-compatibility-and-validation-model2-items.xsd"/> 
</xs:schema> 

這是當你運行XJC agains你會得到什麼型號1:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "typeA", propOrder = { 
    "elA", 
    "any" 
}) 
public class TypeA { 

    @XmlElement(required = true) 
    protected String elA; 
    @XmlAnyElement(lax = true) 
    protected Object any; 

    /** 
    * Gets the value of the elA property. 
    * 
    * @return 
    *  possible object is 
    *  {@link String } 
    *  
    */ 
    public String getElA() { 
     return elA; 
    } 

    /** 
    * Sets the value of the elA property. 
    * 
    * @param value 
    *  allowed object is 
    *  {@link String } 
    *  
    */ 
    public void setElA(String value) { 
     this.elA = value; 
    } 

    /** 
    * Gets the value of the any property. 
    * 
    * @return 
    *  possible object is 
    *  {@link Element } 
    *  {@link Object } 
    *  
    */ 
    public Object getAny() { 
     return any; 
    } 

    /** 
    * Sets the value of the any property. 
    * 
    * @param value 
    *  allowed object is 
    *  {@link Element } 
    *  {@link Object } 
    *  
    */ 
    public void setAny(Object value) { 
     this.any = value; 
    } 

} 

...當你運行XJC agains模型2:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "typeA", propOrder = { 
    "elA", 
    "newElement" 
}) 
public class TypeA { 

    @XmlElement(required = true) 
    protected String elA; 
    @XmlElement(required = true) 
    protected String newElement; 

    /** 
    * Gets the value of the elA property. 
    * 
    * @return 
    *  possible object is 
    *  {@link String } 
    *  
    */ 
    public String getElA() { 
     return elA; 
    } 

    /** 
    * Sets the value of the elA property. 
    * 
    * @param value 
    *  allowed object is 
    *  {@link String } 
    *  
    */ 
    public void setElA(String value) { 
     this.elA = value; 
    } 

    /** 
    * Gets the value of the newElement property. 
    * 
    * @return 
    *  possible object is 
    *  {@link String } 
    *  
    */ 
    public String getNewElement() { 
     return newElement; 
    } 

    /** 
    * Sets the value of the newElement property. 
    * 
    * @param value 
    *  allowed object is 
    *  {@link String } 
    *  
    */ 
    public void setNewElement(String value) { 
     this.newElement = value; 
    } 

} 

Model1和Model2 XSD將按照您預期的方式驗證您的XML。

下面的圖表顯示了XSD文件之間的關係。綠色表示「xsd:include」,箭頭指向「包含」。

QTAssistant XSD file diagram

更新:我剛剛注意到,根據@Kevin的評論,你沒有的maxOccurs在重新定義的新元素。在這種情況下,你可以使用一個單一的重新定義,像這樣:

<?xml version="1.0" encoding="utf-8"?> 
<!--XML Schema generated by QTAssistant/XSR Module (http://www.paschidev.com)--> 
<xsd:schema xmlns="example" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="example" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <xsd:redefine schemaLocation="xsd-allow-extension-compatibility-and-validation.xsd"> 
    <xsd:complexType name="typeA"> 
     <xsd:complexContent> 
     <xsd:restriction base="typeA"> 
      <xsd:sequence> 
      <xsd:element name="elA" type="xsd:string" /> 
      <xsd:element name="newElement" type="xsd:string" /> 
     </xsd:sequence> 
     </xsd:restriction> 
     </xsd:complexContent> 
    </xsd:complexType> 
    </xsd:redefine> 
</xsd:schema> 

唯一的問題似乎是,JAXB(最新)仍然使用通配符生成的類。

更新2:基於Kevin的評論,兩個避免兩個重新定義,應該使用一個組而不是xsd:any。

如果您實際上計劃使用多個元素來擴展新模型,請繼續閱讀。下面是這樣做的唯一方法,這需要使用一組來進一步細化任何粒子。

<?xml version="1.0" encoding="utf-8"?> 
<!--XML Schema generated by QTAssistant/XSR Module (http://www.paschidev.com)--> 
<xsd:schema xmlns="example" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="example" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <xsd:redefine schemaLocation="xsd-allow-extension-compatibility-and-validation.xsd"> 
    <xsd:complexType name="typeA"> 
     <xsd:complexContent> 
     <xsd:restriction base="typeA"> 
      <xsd:sequence> 
        <xsd:element name="elA" type="xsd:string" /> 
        <xsd:group ref="group1" minOccurs="0"> 
     </xsd:sequence> 
     </xsd:restriction> 
     </xsd:complexContent> 
    </xsd:complexType> 
    </xsd:redefine> 
     <xsd:group name="group1"> 
      <xsd:sequence> 
      <xsd:element name="newElement" type="xsd:string" /> 
     </xsd:sequence> 

     </xsd:group> 
</xsd:schema> 

最終的結果是,新的XSD可以用來驗證模型1,而原來的文件保持模型1。

+0

元素粒子可以是任何通配符的有效限制。我認爲你不應該需要使用兩個重新定義,而只需要你進行限制。換句話說,將元素聲明代替限制中的xsd:any。 – Kevin

+0

正確。但是,只有當你添加**一個**元素時,它才能工作。因此,上述工作適用於任何你希望擴展它的方式,並且仍然符合** xsd:any **的初始意圖(我剛纔意識到他沒有使用maxOccurs =「unbounded」,這是我認爲理所當然的)。 –

+0

@PetruGardea謝謝,這正是我需要的。 – rmillet

1

你實際上想要的是一個限制。當您進行擴展時,通配符仍然是內容模型的一部分,這就是您違反唯一粒子屬性的原因。你實際上試圖做的是用通常更具限制性的東西來替換通配符,即特定的元素。