2

我正在学习 XML 和 XSD,但遇到了问题。我想使用以下 XSD 文档验证以下 XML 文档。因为属性“id”用于两个不同的元素。我想将他的定义与 store 和 client 的定义分开,然后在其上使用 ref 。不幸的是,Netbeans 似乎忽略了属性上的引用,或者我做错了,因为当我检查文件 store.xml 时,出现以下错误:

XML validation started.

Checking file:/Users/toto/NetBeansProjects/Cookbook/src/java/store.xml...
Referenced entity at "file:/Users/strokyl/NetBeansProjects/Cookbook/src/java/store.xsd".
cvc-complex-type.3.2.2: Attribute 'id' is not allowed to appear in element 'client'. [14] 
cvc-complex-type.3.2.2: Attribute 'id' is not allowed to appear in element 'client'. [19] 
cvc-complex-type.3.2.2: Attribute 'id' is not allowed to appear in element 'client'. [24] 
cvc-complex-type.3.2.2: Attribute 'id' is not allowed to appear in element 'product'. [32] 
cvc-complex-type.3.2.2: Attribute 'id' is not allowed to appear in element 'product'. [39] 
cvc-complex-type.3.2.2: Attribute 'id' is not allowed to appear in element 'product'. [46]

当我用<xs:attribute ref="id"/>客户端和商店上的 id 属性的定义替换时,xml 正确有效!

提前感谢您的宝贵帮助,并为我糟糕的英语(我是法国人)感到抱歉。

XML 文件 (store.xml)

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

<!--
    Document   : store.xml.xml
    Created on : 12 novembre 2013, 22:09
    Author     : strokyl
    Description:
        Purpose of the document follows.
-->
<store xmlns="http://etud.insa-toulouse.fr/~duzan/store"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation='http://etud.insa-toulouse.fr/~duzan/store store.xsd'>
    <clients>
        <client id="1">
            <first_name>Luc</first_name>
            <last_name>Duzan</last_name>
            <age>22</age>
        </client>
        <client id="2">
            <first_name>Adrien</first_name>
            <last_name>Gareau</last_name>
            <age>22</age>
        </client>
        <client id="3">
            <first_name>Gilles</first_name>
            <last_name>Roudière</last_name>
            <age>22</age>
        </client>
    </clients>

    <products>
        <product id="1">
            <name>Poster de Maxime Médard</name>
  <!-- You don’t have to use same convention that you use for relational database -->
            <categorie>Poster</categorie>
            <price>10</price>
            <number_in_stock>100</number_in_stock>
        </product>
        <product id="2">
            <name>Poster de Yannick Jauzion</name>
            <categorie>Poster</categorie>
            <price>10</price>
            <number_in_stock>200</number_in_stock>
        </product>

        <product id="3">
            <name>Drapeau du stade toulousain</name>
            <categorie>drapeau</categorie>
            <price>5</price>
            <number_in_stock>500</number_in_stock>
        </product>
    </products>
</store>

xml 架构文件 (store.xsd)

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://etud.insa-toulouse.fr/~duzan/store"
    xmlns="http://etud.insa-toulouse.fr/~duzan/store"
    elementFormDefault="qualified">

    <xs:element name="store">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="clients"/>
                <xs:element ref="products"/>
                <xs:any/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

<!-- Definition très exposé de clients -->

    <xs:element name="first_name" type="xs:string"/>
    <xs:element name="last_name" type="xs:string"/>

    <xs:element name="age">
        <xs:simpleType>
            <xs:restriction base="xs:integer">
                <xs:minInclusive value="0"/>
                <xs:maxInclusive value="120"/>
            </xs:restriction>
        </xs:simpleType>
    </xs:element>

    <xs:attribute name="id" type="xs:integer"/>

    <xs:complexType name="client_type">
        <xs:sequence>
            <xs:element ref="first_name"/>
            <xs:element ref="last_name"/>
            <xs:element ref="age"/>
        </xs:sequence>
        <xs:attribute ref="id"/>
    </xs:complexType>

    <xs:element name="client" type="client_type"/>

    <xs:complexType name="clients_type">
        <xs:sequence>
            <xs:element ref="client" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>

    <xs:element name="clients" type="clients_type"/>

<!-- Definition très condensé de product à part qu'on réutilise l'attribut id définit plus tôt -->
    <xs:element name="products">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="product" minOccurs="0" maxOccurs="unbounded">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="name" type="xs:string"/>
                            <xs:element name="categorie" type="xs:string"/>
                            <xs:element name="price">
                                <xs:simpleType>
                                    <xs:restriction base="xs:integer">
                                        <xs:minInclusive value="0"/>
                                    </xs:restriction>
                                </xs:simpleType>
                            </xs:element>

                            <xs:element name="number_in_stock">
                                <xs:simpleType>
                                    <xs:restriction base="xs:integer">
                                        <xs:minInclusive value="0"/>
                                        <xs:maxInclusive value="1000"/>
                                    </xs:restriction>
                                </xs:simpleType>
                            </xs:element>

                        </xs:sequence>
                        <xs:attribute ref="id"/>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>
4

2 回答 2

3

问题是顶级属性声明采用targetNamespace了模式。因此,验证器正在寻找命名空间id中的一个名为的属性http://etud.insa-toulouse.fr/~duzan/store,但您的文档却包含一个不在id命名空间中的名为的属性(因为默认的 xmlns 声明不适用于属性)。

要对现有架构有效,您需要将前缀绑定到命名空间并将该前缀用于属性

<store xmlns="http://etud.insa-toulouse.fr/~duzan/store"
      xmlns:store="http://etud.insa-toulouse.fr/~duzan/store">
  <!-- ... -->
  <client store:id="1">

相比之下,复杂类型内的局部属性声明不在命名空间中(除非您attributeFormDefault在模式或form特定声明中指定)。因此,另一种选择可能是声明一个带有属性的基类型,然后让你的其他类型扩展它。

<xs:complexType name="identifiedType">
  <xs:attribute name="id" type="xs:integer"/>
</xs:complexType> 

<xs:complexType name="client_type">
  <xs:complexContent>
    <xs:extension base="identifiedType">
      <xs:sequence>
        <xs:element ref="first_name"/>
        <xs:element ref="last_name"/>
        <xs:element ref="age"/>
      </xs:sequence>
    </xs:extension>
  </xs:complexContent>
</xs:complexType>

id 属性现在是本地声明而不是全局声明。

于 2013-11-14T09:09:14.933 回答
0

我同意前面的答案,但只是为了让它更简单:

实际上,属性的问题在于,如果要指定全局声明以供重用(我的意思是在复杂类型之外),则需要在使用它们的 xml 实例中限定属性。

在您的情况下,您需要在 store.xml 实例中执行以下操作:

1)为您的商店声明的名称空间添加一个前缀,例如“ xmlns:store="http://etud.insa-toulouse.fr/~duzan/store" ”:

<store xmlns="http://etud.insa-toulouse.fr/~duzan/store"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xmlns:store="http://etud.insa-toulouse.fr/~duzan/store"

    xsi:schemaLocation='http://etud.insa-toulouse.fr/~duzan/store store.xsd'>

2)然后您需要限定属性,例如store:id

<clients>
    <client store:id="1">
        <first_name>Luc</first_name>
        <last_name>Duzan</last_name>
        <age>22</age>
    </client>

我的建议:

  • 为什么要使用属性?SOA 中的实践是在可能的情况下使用元素(当然不是每个人都这么认为..)
  • 如果你真的需要它们,那么只使用属性的本地声明(在复杂类型中)以避免在实例中冗长命名空间。
于 2013-11-17T14:55:42.833 回答