3

我想为一个应用程序创建一个 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>

必须对第一个 XSD(但不是第二个)有效的 XML 示例:

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

必须对两个XSD都有效的 XML 示例

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

以前的 XSD 违反了“唯一粒子属性”,我希望修复这个问题。我可以编辑两个 XSD,但我希望能够在完成第二个之前分发第一个。

我怎样才能做到这一点(当由 JAXB 检查时,两个模式都必须有效)?

谢谢

4

2 回答 2

1

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

于 2012-09-25T19:52:43.593 回答
1

有人可能会说:如果你可以编辑两个 XSD,为什么还要重新定义呢?

我将向您展示如何使它与 XSD 重新定义一起工作,至少从 XSD 的角度来看。但是,鉴于 JAXB 的限制,它不能开箱即用。如果您还使用自动 XSD 重构作为额外的步骤,那么您可以使其工作,并且在此过程中,您将保留您在使用 xsd:redefine 时看到的价值主张。

因此,在此之前,这是另一种也使用组合但没有xsd:redefine; 从维护和验证的角度来看,您获得的价值和使用情况大致相同。

我将您的第一个 XSD 称为Model1,将您的第二个 XSD 称为Model2. 我将从一个 XSD 开始,它将为您提供与xs:redefine.

常见项目,xsd-allow-extension-compatibility-and-validation-common-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> 

Model1“项目”,xsd-allow-extension-compatibility-and-validation-model1-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:any namespace="##any" minOccurs="0" processContents="lax" /> 
    </xs:sequence> 
  </xs:complexType>  
</xs:schema> 

Model2“项目”,xsd-allow-extension-compatibility-and-validation-model2-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> 

如果您将 Common Items 和 Model1,或 Common Items 和 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>

这是您在 Model1 上运行 xjc 时得到的结果:

@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 模型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文件图

更新:我刚刚注意到,根据@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 可用于验证 Model1,而原始文件仍然是 Model1。

于 2012-09-25T22:06:00.980 回答