2012-09-25 107 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

你实际上想要的是一个限制。当您进行扩展时,通配符仍然是内容模型的一部分,这就是您违反唯一粒子属性的原因。你实际上试图做的是用通常更具限制性的东西来替换通配符,即特定的元素。