通过扩展/继承具有附加属性的一组共享XML类型来最小化耦合

时间:2012-07-31 00:33:10

标签: xml oop inheritance xsd encapsulation

我想解耦两个共享一组XML类型的开发团队的顾虑。共享类型在共享XSD中定义。但是,第二个团队需要在共享XML类型中的大多数字段上添加一组属性,这些属性仅与其要求集相关。目前,这些专有属性嵌入在共享XSD的大多数字段中。

我想将这些属性隔离到一组扩展共享XML类型的XML类型,就像在简单的OO语言中一样。 Ayesha Malik有一些想法让我开始使用Building XML schemas in an object-oriented framework

的技术

感谢to add attributes ... to add facets 我能够为各个字段的complexTypes添加属性。但是当我尝试覆盖其中一个复杂的共享类型中的子元素的类型时,Eclipse中的验证会抱怨

  

粒子类型不是粒子的有效限制   基

如果我将各个子元素类型保持不变,则验证效果非常好。但是,如果我将其类型更改为新的派生类型,则验证将失败。这令人沮丧,因为各个子元素的类型与父类型不同的事实是练习的重点。我想为父类型中的每个字段/子元素添加一组属性,我没有看到任何方法。

我分离了一个示例,该示例演示了您可以使用simpleContent将属性添加到simpleType和complextType。但是我无法使用complextContent将属性添加到派生的complexType中。例如,在下面的complexType“SearchPamphlet”中,我尝试使用< xs:extension>和< xs:restriction>。我也尝试将'base'设置为“Book”和“Pamphlet”。所有这些方法都产生相同的错误。有没有人有任何建议?

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

    <xs:complexType name="Book">
        <xs:sequence>
            <xs:element name="Title" type="xs:string" />
            <xs:element name="Author" type="xs:string" />
            <xs:element name="ISBN" type="xs:string" />
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="Pamphlet">
        <xs:complexContent>
            <xs:restriction base="Book">
                <xs:sequence>
                    <xs:element name="Title" type="xs:string" />
                    <xs:element name="Author" type="xs:string" />
                    <xs:element name="ISBN" type="PamphletISBN" />
                </xs:sequence>
            </xs:restriction>
        </xs:complexContent>
    </xs:complexType>

    <xs:simpleType name="ISBNType">
        <xs:restriction base="xs:string" />
    </xs:simpleType>

    <xs:simpleType name="PamphletISBN">
        <xs:restriction base="ISBNType">
            <xs:maxLength value="5" />
        </xs:restriction>
    </xs:simpleType>

    <xs:complexType name="SearchablePamphlet">
        <xs:complexContent>
            <xs:restriction base="Book">
                <xs:sequence>
                    <xs:element name="Title" type="SearchableString" />
                    <xs:element name="Author" type="SearchableString" />
                    <xs:element name="ISBN" type="SearchablePamphletISBN" />
                </xs:sequence>
            </xs:restriction>
        </xs:complexContent>
    </xs:complexType>

    <xs:complexType name="SearchablePamphletISBN">
        <xs:simpleContent>
            <xs:extension base="PamphletISBN">
            <xs:attributeGroup ref="searchableAttributes" />
            </xs:extension>
        </xs:simpleContent>
    </xs:complexType>

    <xs:complexType name="SearchableString">
        <xs:simpleContent>
            <xs:extension base="xs:string">
                <xs:attributeGroup ref="searchableAttributes" />
            </xs:extension>
        </xs:simpleContent>
    </xs:complexType>

    <xs:attributeGroup name="searchableAttributes">
        <xs:attribute name="caseMatches" type="xs:boolean" />
        <xs:attribute name="spellingMatches" type="xs:boolean" />
        <xs:attribute name="checksum" type="xs:integer" />
    </xs:attributeGroup>

</xs:schema>

3 个答案:

答案 0 :(得分:0)

下面的XSD严格匹配您发布的来源的意图。重点是让您了解限制在XSD中是如何工作的,以及您在创作中需要考虑的开销。

要解释:您需要以“SearcheableBook”开头,而不是已经 受限制 的Book,这是一个拥有您所需要的实体,并且可以从中获取,你通过各种限制缩减。

<?xml version="1.0" encoding="UTF-8"?>
<!--XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com)-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:complexType name="SearchableBook" abstract="true">
        <xs:sequence>
            <xs:element name="Title" type="SearchableString"/>
            <xs:element name="Author" type="SearchableString"/>
            <xs:element name="ISBN" type="SearchableString"/>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="Book">
        <xs:complexContent>
            <xs:restriction base="SearchableBook">
                <xs:sequence>
                    <xs:element name="Title" type="SimpleTitle"/>
                    <xs:element name="Author" type="SimpleAuthor"/>
                    <xs:element name="ISBN" type="SimpleISBN"/>
                </xs:sequence>
            </xs:restriction>
        </xs:complexContent>
    </xs:complexType>

    <xs:complexType name="SimpleTitle">
        <xs:simpleContent>
            <xs:restriction base="SearchableString">
                <xs:attribute name="caseMatches" type="xs:boolean" use="prohibited"/>
                <xs:attribute name="spellingMatches" type="xs:boolean" use="prohibited"/>
                <xs:attribute name="checksum" type="xs:integer" use="prohibited"/>              
            </xs:restriction>
        </xs:simpleContent>     
    </xs:complexType>

    <xs:complexType name="SimpleAuthor">
        <xs:simpleContent>
            <xs:restriction base="SearchableString">
                <xs:attribute name="caseMatches" type="xs:boolean" use="prohibited"/>
                <xs:attribute name="spellingMatches" type="xs:boolean" use="prohibited"/>
                <xs:attribute name="checksum" type="xs:integer" use="prohibited"/>                              
            </xs:restriction>
        </xs:simpleContent>
    </xs:complexType>

    <xs:complexType name="SimpleISBN">
        <xs:simpleContent>
            <xs:restriction base="SearchableString">
                <xs:attribute name="caseMatches" type="xs:boolean" use="prohibited"/>
                <xs:attribute name="spellingMatches" type="xs:boolean" use="prohibited"/>
                <xs:attribute name="checksum" type="xs:integer" use="prohibited"/>                              
            </xs:restriction>
        </xs:simpleContent>
    </xs:complexType>

    <xs:complexType name="Pamphlet">
        <xs:complexContent>
            <xs:restriction base="SearchableBook">
                <xs:sequence>
                    <xs:element name="Title" type="SimpleTitle"/>
                    <xs:element name="Author" type="SimpleAuthor"/>
                    <xs:element name="ISBN" type="PamphletISBN"/>
                </xs:sequence>
            </xs:restriction>
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="PamphletISBN">
        <xs:simpleContent>
            <xs:restriction base="SearchableString">
                <xs:maxLength value="5"/>
                <xs:attribute name="caseMatches" type="xs:boolean" use="prohibited"/>
                <xs:attribute name="spellingMatches" type="xs:boolean" use="prohibited"/>
                <xs:attribute name="checksum" type="xs:integer" use="prohibited"/>                              
            </xs:restriction>
        </xs:simpleContent>
    </xs:complexType>

    <xs:complexType name="SearchablePamphlet">
        <xs:complexContent>
            <xs:restriction base="SearchableBook">
                <xs:sequence>
                    <xs:element name="Title" type="SearchableString"/>
                    <xs:element name="Author" type="SearchableString"/>
                    <xs:element name="ISBN" type="SearchablePamphletISBN"/>
                </xs:sequence>
            </xs:restriction>
        </xs:complexContent>
    </xs:complexType>

    <xs:complexType name="SearchablePamphletISBN">
        <xs:simpleContent>
            <xs:restriction base="SearchableString">
                <xs:maxLength value="5"/>
            </xs:restriction>
        </xs:simpleContent>
    </xs:complexType>
    <xs:complexType name="SearchableString">
        <xs:simpleContent>
            <xs:extension base="xs:string">
                <xs:attributeGroup ref="searchableAttributes"/>
            </xs:extension>
        </xs:simpleContent>
    </xs:complexType>
    <xs:attributeGroup name="searchableAttributes">
        <xs:attribute name="caseMatches" type="xs:boolean"/>
        <xs:attribute name="spellingMatches" type="xs:boolean"/>
        <xs:attribute name="checksum" type="xs:integer"/>
    </xs:attributeGroup>
</xs:schema> 

另外,我会尝试以不同的方式思考模型,使用扩展,看看它是否可以以我称之为更清洁的方式完成(我最近看到一个复杂的限制案例如何阻塞最昂贵的XSD编辑器市场......)

答案 1 :(得分:0)

感谢您的回复。它在语法上有效。遗憾的是,答案仅适用于只有单个派生类型集的示例场景。在多个开发团队从共享类型的公共库中工作的情况下,这不会扩展。

例如,在存在包含示例类型的共享类型的标准公司库的情况下,预订&#34;,&#34; 小册子< /强>&#34;和&#34; PamphletISBN &#34;和库XSD文件是&#34; 冻结&#34;通过标准程序。

在这种情况下,搜索小组无法修改 Book 类型,也不会真正想要它们。因为其他开发团队有竞争要求。例如,销售团队希望拥有&#34; lifeTimeSales &#34;,&#34; topRanking &#34;,&#34; highestRatings &#34;等,而制作团队可能希望为&#34; monthlyPrinting &#34;,&#34; 添加属性numberInInventory &#34;等


从昨天开始,我尝试使用 元素 解决此问题。不幸的是,这种方法也不会超出单一类型的水平。

我要调查的另一种方法是使用替换组,看看是否会开辟任何途径。如果我找到解决方案,我会发布它。

再次感谢您的建议。

答案 2 :(得分:0)

我找到了一个解决方案,可以解决我所关注的问题。 解决方案是使用“ Salami Slice ”设计模式,并结合 substitutionGroup

有了无所不知且有先见之明的分析师,基础文件可能会预测非常需要发展,或者如果公司的标准委员会可以在每次公司的开发小组出现时更改基本类型的XSD文件还有他们想要添加的另一个元素或属性。但在我职业生涯中的工作经历中,我从未有机会与这样的个人合作,也没有这样的标准委员会。

我发布了三个XSD文件,这些文件演示了以下关注点的隔离以及示例XML文件。在发布的代码中,我假设BaseTypes.xsd文件被冻结并且在更改审核委员会的控制下。我还假设DerivedTypes.xsd,Products.xsd和Test.xml文件将由本地产品开发组生成:

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- XMLInheritance_BaseDataTypes -->

    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
      targetNamespace="http://www.company.org/XMLInheritance" xmlns:bk="http://www.company.org/XMLInheritance"
      elementFormDefault="qualified" attributeFormDefault="unqualified">

      <xs:element name="Book" type="bk:BookType" />
      <xs:element name="Title" type="xs:string" />
      <xs:element name="Author" type="xs:string" />
      <xs:element name="ISBN" type="bk:ISBNType" />

      <xs:simpleType name="ISBNType">
        <xs:restriction base="xs:string" />
      </xs:simpleType>

      <xs:complexType name="BookType">
        <xs:sequence>
          <xs:element ref="bk:Title" />
          <xs:element ref="bk:Author" />
          <xs:element ref="bk:ISBN" />
        </xs:sequence>
      </xs:complexType>

    </xs:schema>


    ----------

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- XMLInheritance_DerivedDataTypes -->

    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
      targetNamespace="http://www.company.org/XMLInheritance" xmlns:bk="http://www.company.org/XMLInheritance"
      elementFormDefault="qualified" attributeFormDefault="unqualified">

      <xs:include schemaLocation="XMLInheritance_BaseDataTypes.xsd" />

      <xs:element name="SearchableBook" type="bk:SearchableBookType"
        substitutionGroup="bk:Book" />
      <xs:element name=" SearchableTitle " type="bk:SearchableString"
        substitutionGroup="bk:Title" />
      <xs:element name="SearchableAuthor" type="bk:SearchableString"
        substitutionGroup="bk:Author" />
      <xs:element name="SearchableISBN" type="bk:SearchableISBNType"
        substitutionGroup="bk:ISBN" />

      <xs:attributeGroup name="searchableAttributes">
        <xs:attribute name="caseMatches" type="xs:boolean" />
        <xs:attribute name="spellingMatches" type="xs:boolean" />
        <xs:attribute name="checksum" type="xs:integer" />
      </xs:attributeGroup>

      <xs:complexType name="SearchableBookType">
        <xs:complexContent>
          <xs:restriction base="bk:BookType">
            <xs:sequence>
              <xs:element ref="bk:SearchableTitle" />
              <xs:element ref="bk:SearchableAuthor" />
              <xs:element ref="bk:SearchableISBN" />
            </xs:sequence>
          </xs:restriction>
        </xs:complexContent>
      </xs:complexType>

      <xs:complexType name="SearchableISBNType">
        <xs:simpleContent>
          <xs:extension base="bk:ISBNType">
            <xs:attributeGroup ref="bk:searchableAttributes" />
          </xs:extension>
        </xs:simpleContent>
      </xs:complexType>

      <xs:complexType name="SearchableString">
        <xs:simpleContent>
          <xs:extension base="xs:string">
            <xs:attributeGroup ref="bk:searchableAttributes" />
          </xs:extension>
        </xs:simpleContent>
      </xs:complexType>

    </xs:schema>


    ----------
    <?xml version="1.0" encoding="UTF-8"?>
    <!-- XMLInheritance_DerivedProducts.xsd -->

    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
      targetNamespace="http://www.company.org/XMLInheritance" xmlns:bk="http://www.company.org/XMLInheritance"
      elementFormDefault="qualified">
      <xs:include schemaLocation="XMLInheritance_DataTypes.xsd" />

      <xs:element name="Product">
        <xs:complexType>
          <xs:sequence>

            <xs:element name="Books">
              <xs:complexType>
                <xs:sequence maxOccurs="unbounded">
                  <xs:element name="Book" type="bk:BookType" />
                </xs:sequence>
              </xs:complexType>
            </xs:element>

            <xs:element name="SearchableBooks" minOccurs="0">
              <xs:complexType>
                <xs:sequence maxOccurs="unbounded">
                  <xs:element name="SearchableBook" type="bk:SearchableBookType" />
                </xs:sequence>
              </xs:complexType>
            </xs:element>
          </xs:sequence>
        </xs:complexType>
      </xs:element>

    </xs:schema>


    ----------
    <?xml version="1.0" encoding="UTF-8"?>
    <!-- XMLInheritance_Test.xml -->
    <bk:Product xmlns:bk="http://www.company.org/XMLInheritance"
      xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
      xs:schemaLocation="http://www.company.org/XMLInheritance XMLInheritance_DerivedProducts.xsd ">

      <bk:Books>
        <bk:Book>
          <bk:Title>Title</bk:Title>
          <bk:Author>Author</bk:Author>
          <bk:ISBN>ISBN</bk:ISBN>
        </bk:Book>
      </bk:Books>
      <bk:SearchableBooks>
        <bk:SearchableBook>
          <bk:SearchableTitle>Searchable Title</bk:SearchableTitle>
          <bk:SearchableAuthor>Searchable Author</bk:SearchableAuthor>
          <bk:SearchableISBN>Searchable ISBN</bk:SearchableISBN>
        </bk:SearchableBook>
      </bk:SearchableBooks>

    </bk:Product>