关系XML Schema不能很好地工作

时间:2018-01-31 19:33:09

标签: xml xsd xmlschemaset

我一直在研究基于非常易于理解的数据库表的xsd文件。想象一下“用户”。这些用户具有普通字段(名字,姓氏等),并且还具有电话和地址字段(每个用户可以具有多个电话和地址)。我想为这种关系创建最好的XML Schema,以便我将来根据预定的Schema生成xsd文件。

所以我为我的XML Schema得到了这个(但我认为重要的部分是实现我的键和keyrefs的地方)

<?xml version="1.0" encoding="utf-8"?>
<xs:schema
  elementFormDefault="qualified"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">

  <xs:element name="Root" msdata:IsDataSet="true">
    <xs:annotation>
      <xs:documentation>Contains All Object</xs:documentation>
    </xs:annotation>
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="User" maxOccurs="unbounded">
        </xs:element>
        <xs:element ref="UserPhone" maxOccurs="unbounded" />
        <xs:element ref="UserAddress" maxOccurs="unbounded" />
        <xs:element ref="AddressLine" maxOccurs="unbounded" />
      </xs:sequence>
    </xs:complexType>
    <xs:key name="UserUID">
      <xs:selector xpath="User" />
      <xs:field xpath="UserUID" />
    </xs:key>
    <xs:key name="PhoneUID">
      <xs:selector xpath="UserPhone" />
      <xs:field xpath="PhoneUID" />
    </xs:key>
    <xs:key name="AddressUID">
      <xs:selector xpath="UserAddress" />
      <xs:field xpath="AddressUID" />
    </xs:key>
    <xs:key name="AddressLineUID">
      <xs:selector xpath="AddressLine" />
      <xs:field xpath="AddressLineUID" />
    </xs:key>
    <xs:keyref name="FKPhonetoUsers" refer="PhoneUID">
      <xs:selector xpath="User/UserPhones/*" />
      <xs:field xpath="PhoneUID" />
    </xs:keyref>
    <xs:keyref name="FKAddresstoUsers" refer="AddressUID">
      <xs:selector xpath="User/UserAddresses/*" />
      <xs:field xpath="AddressUID" />
    </xs:keyref>
    <xs:keyref name="FKAddressLinetoAddresses" refer="AddressLineUID">
      <xs:selector xpath="UserAddress/AddressLines/*" />
      <xs:field xpath="AddressLineUID" />
    </xs:keyref>
  </xs:element>

  <xs:element name="User">
    <xs:annotation>
      <xs:documentation>Contains All Employee Information</xs:documentation>
    </xs:annotation>
    <xs:complexType>
      <xs:sequence>
        <xs:element name="UserUID" type="xs:string" />
        <xs:element name="UserFirstName" type="xs:string" />
        <xs:element name="UserLastName" type="xs:string" />
        <xs:element name="UserIDLogin" type="IDLoginPatern" />
        <xs:element name="UserEmail" type="EmailPatern" />
        <xs:element name="UserPhones">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="PhoneUID" maxOccurs="3" type="xs:string" />
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:element name="UserDepartment" type="xs:nonNegativeInteger" default="0" />
        <xs:element name="UserSector" type="xs:string" />
        <xs:element name="UserTitle" type="TitleEnum" />
        <xs:element name="UserAddresses">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="AddressUID" maxOccurs="2" type="xs:string" />
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:element name="UserOfSystem" type="xs:boolean" />
        <xs:element name="UserRole" type="xs:string" />
        <xs:element name="UserPW" type="PWordPatern" />
        <xs:element name="UserPWFailCount" type="xs:nonNegativeInteger" default="0"/>
        <xs:element name="UserPWFailDate" type="xs:date" minOccurs="0" />
        <xs:element name="UserProfileCreated" type="xs:date" />
        <xs:element name="UserLastAccessSystem" type="xs:date" minOccurs="0" />
        <xs:element name="UserPic" type="xs:anyURI" minOccurs="0" />
        <xs:element name="SSMA_TimeStamp" type="xs:base64Binary" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name="UserPhone">
    <xs:annotation>
      <xs:documentation>Contains All Phone Created</xs:documentation>
    </xs:annotation>
    <xs:complexType>
      <xs:sequence>
        <xs:element name="PhoneUID" type="xs:string" />
        <xs:element name="type" type="TelephoneTypeEnum" />
        <xs:element name="number" type="TelephonePatern" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name="UserAddress">
    <xs:annotation>
      <xs:documentation>Contains All Address Created</xs:documentation>
    </xs:annotation>
    <xs:complexType>
      <xs:sequence>
        <xs:element name="AddressUID" type="xs:string" />
        <xs:element name="AddressLines">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="AddressLineUID" maxOccurs="2" type="xs:string" />
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:element name="city" type="xs:string"/>
        <xs:element name="state" type="xs:string"/>
        <xs:element name="country" type="xs:string"/>
        <xs:element name="postalCode" type="xs:string"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name="AddressLine">
    <xs:annotation>
      <xs:documentation>Contains All Address Line Completing the Address Objects Created</xs:documentation>
    </xs:annotation>
    <xs:complexType>
      <xs:sequence>
        <xs:element name="AddressLineUID" type="xs:string" />
        <xs:element name="streetLine" type="xs:string"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <!-- All Telephone patern (123) 456-7890 -->
  <xs:simpleType name="TelephonePatern">
    <xs:restriction base="xs:string">
      <xs:pattern value="\([0-9]{3}\) [0-9]{3}-[0-9]{4}"/>
    </xs:restriction>
  </xs:simpleType>

  <!-- All ID Login patern (LOGINONE) -->
  <xs:simpleType name="IDLoginPatern">
    <xs:restriction base="xs:string">
      <xs:pattern value="[A-Z]+"/>
    </xs:restriction>
  </xs:simpleType>

  <!-- All Email patern (blabla@gmail.com) -->
  <xs:simpleType name="EmailPatern">
    <xs:restriction base="xs:string">
      <xs:pattern value="[^@]+@[^\.]+\..+"/>
    </xs:restriction>
  </xs:simpleType>

  <!-- All Password patern (aaaaa) -->
  <xs:simpleType name="PWordPatern">
    <xs:restriction  base="xs:string">
      <xs:minLength  value="4" />
      <xs:maxLength  value="30" />
      <xs:pattern  value="[a-zA-Z0-9\p{P}$\^\+=~`|]+" />
    </xs:restriction>
  </xs:simpleType>

  <!-- Person title enumeration -->
  <xs:simpleType name="TitleEnum" final="restriction" >
    <xs:restriction base="xs:string">
      <xs:enumeration value="Mr." />
      <xs:enumeration value="Ms." />
      <xs:enumeration value="Miss" />
    </xs:restriction>
  </xs:simpleType>

  <!-- Telephone type enumeration -->
  <xs:simpleType name="TelephoneTypeEnum" final="restriction" >
    <xs:restriction base="xs:string">
      <xs:enumeration value="Work" />
      <xs:enumeration value="Home" />
      <xs:enumeration value="Fax" />
      <xs:enumeration value="Personal" />
    </xs:restriction>
  </xs:simpleType>

</xs:schema>

之后,我创建了一个小的XML文件来测试我的所有密钥,格式,模式和枚举是否都运行良好。

这是我到目前为止所得到的:

<?xml version="1.0" encoding="utf-8"?>
<Root>
  <User>
    <UserUID>UserUID1</UserUID>
    <UserFirstName>UserFirstName1</UserFirstName>
    <UserLastName>UserLastName1</UserLastName>
    <UserIDLogin>USERONE</UserIDLogin>
    <UserEmail>userone@gmail.com</UserEmail>
    <UserPhones>
      <PhoneUID>PhoneUID1</PhoneUID>
      <PhoneUID>PhoneUID2</PhoneUID>
      <PhoneUID>PhoneUID4</PhoneUID>
    </UserPhones>
    <UserDepartment>0</UserDepartment>
    <UserSector>UserSector1</UserSector>
    <UserTitle>Mr.</UserTitle>
    <UserAddresses>
      <AddressUID>AddressUID1</AddressUID>
      <AddressUID>AddressUID2</AddressUID>
    </UserAddresses>
    <UserOfSystem>true</UserOfSystem>
    <UserRole>UserRole1</UserRole>
    <UserPW>UserPW1</UserPW>
    <UserPWFailCount>0</UserPWFailCount>
    <UserPWFailDate>1900-01-01</UserPWFailDate>
    <UserProfileCreated>1900-01-01</UserProfileCreated>
    <UserLastAccessSystem>1900-01-01</UserLastAccessSystem>
    <UserPic>http://uri1</UserPic>
    <SSMA_TimeStamp>AAECAwQFBgcICQoLDA0ODw==</SSMA_TimeStamp>
  </User>
  <UserPhone>
    <PhoneUID>PhoneUID1</PhoneUID>
    <type>Work</type>
    <number>(613) 333-4455</number>
  </UserPhone>
  <UserPhone>
    <PhoneUID>PhoneUID2</PhoneUID>
    <type>Home</type>
    <number>(613) 444-5566</number>
  </UserPhone>
  <UserPhone>
    <PhoneUID>PhoneUID3</PhoneUID>
    <type>Fax</type>
    <number>(613) 555-6677</number>
  </UserPhone>
  <UserAddress>
    <AddressUID>AddressUID1</AddressUID>
    <AddressLines>
      <AddressLineUID>AddressLineUID1</AddressLineUID>
      <AddressLineUID>AddressLineUID2</AddressLineUID>
    </AddressLines>
    <city>city1</city>
    <state>state1</state>
    <country>country1</country>
    <postalCode>postalCode1</postalCode>
  </UserAddress>
  <UserAddress>
    <AddressUID>AddressUID2</AddressUID>
    <AddressLines>
      <AddressLineUID>AddressLineUID3</AddressLineUID>
      <AddressLineUID>AddressLineUID4</AddressLineUID>
    </AddressLines>
    <city>city2</city>
    <state>state2</state>
    <country>country2</country>
    <postalCode>postalCode2</postalCode>
  </UserAddress>
  <AddressLine>
    <AddressLineUID>AddressLineUID2</AddressLineUID>
    <streetLine>streetLine2</streetLine>
  </AddressLine>
  <AddressLine>
    <AddressLineUID>AddressLineUID3</AddressLineUID>
    <streetLine>streetLine3</streetLine>
  </AddressLine>
</Root>

我已经测试了两个文件并且它运行良好但我不认为它应该工作。我不明白我做错了什么。因为,因为我在我的键之间有引用,为什么行:

<PhoneUID>PhoneUID4</PhoneUID>

在我的XML文件中工作正常吗?我没有使用id: PhoneUID4 创建任何“UserPhone”。

我在那里测试了我的文件:http://www.utilities-online.info/xsdvalidation/#.WnIPJq6nGUk

你能帮我解决这个问题吗?

非常感谢, 文森特

1 个答案:

答案 0 :(得分:1)

您将keyref定义为

<xs:keyref name="FKPhonetoUsers" refer="PhoneUID">
    <xs:selector xpath="User/UserPhones/*" />
    <xs:field xpath="PhoneUID" />
</xs:keyref>

现在,User/UserPhones/*会选择三个PhoneUID元素。相对于这些元素评估xs:field表达式。这些都没有一个名为PhoneUID的孩子,因此没有选择任何内容,因此没有任何内容得到验证。将xs:field更改为xpath=".",效果很好。

你显然沉浸在SQL思维中,SQL用户使用XPath常犯的一个错误就是忘记使用元素名称X意味着child::X而不是self::X