关系 XML 架构运行不正常
Relational XML Schema isn't working perfectly
我一直在基于一个非常容易理解的数据库表来处理 xsd 文件。想象一下 "users"。这些用户有普通字段(名字、姓氏等),还有一个 phone 和一个地址字段(每个用户可以有多个 phone 和地址)。我想为这种关系创建最好的 XML 模式,以便我将来根据预定模式生成 xsd 文件。
所以我为我的 XML 模式得到了这个(但我认为重要的部分是实现我的键和 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 创建任何 "UserPhone":PhoneUID4.
我在那里测试了我的文件:http://www.utilities-online.info/xsdvalidation/#.WnIPJq6nGUk
你能帮我解决这个问题吗?
非常感谢,
文森特
您将 keyref 定义为
<xs:keyref name="FKPhonetoUsers" refer="PhoneUID">
<xs:selector xpath="User/UserPhones/*" />
<xs:field xpath="PhoneUID" />
</xs:keyref>
现在,User/UserPhones/*
选择三个 PhoneUID
元素。 xs:field
表达式是相对于这些元素求值的。 None 其中有一个名为 PhoneUID
的子项,因此未选择任何内容,因此未验证任何内容。将 xs:field
更改为 xpath="."
,它工作正常。
您显然沉浸在 SQL 思维中,SQL 用户使用 XPath 时常犯的错误之一是忘记使用元素名称 X 意味着 child::X
而不是比 self::X
.
我一直在基于一个非常容易理解的数据库表来处理 xsd 文件。想象一下 "users"。这些用户有普通字段(名字、姓氏等),还有一个 phone 和一个地址字段(每个用户可以有多个 phone 和地址)。我想为这种关系创建最好的 XML 模式,以便我将来根据预定模式生成 xsd 文件。
所以我为我的 XML 模式得到了这个(但我认为重要的部分是实现我的键和 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 创建任何 "UserPhone":PhoneUID4.
我在那里测试了我的文件:http://www.utilities-online.info/xsdvalidation/#.WnIPJq6nGUk
你能帮我解决这个问题吗?
非常感谢, 文森特
您将 keyref 定义为
<xs:keyref name="FKPhonetoUsers" refer="PhoneUID">
<xs:selector xpath="User/UserPhones/*" />
<xs:field xpath="PhoneUID" />
</xs:keyref>
现在,User/UserPhones/*
选择三个 PhoneUID
元素。 xs:field
表达式是相对于这些元素求值的。 None 其中有一个名为 PhoneUID
的子项,因此未选择任何内容,因此未验证任何内容。将 xs:field
更改为 xpath="."
,它工作正常。
您显然沉浸在 SQL 思维中,SQL 用户使用 XPath 时常犯的错误之一是忘记使用元素名称 X 意味着 child::X
而不是比 self::X
.