如何使用包含来自另一个命名空间的keyref的XSD创建XML实例
我试图验证一个依赖于另一个实例(来自不同名称空间)的XML实例,它在该名称空间中有一个键引用。当我尝试验证实例时,它会产生一个错误,表示密钥超出范围 这些是我的XSD: test1.xsd如何使用包含来自另一个命名空间的keyref的XSD创建XML实例,xml,namespaces,xsd,keyref,Xml,Namespaces,Xsd,Keyref,我试图验证一个依赖于另一个实例(来自不同名称空间)的XML实例,它在该名称空间中有一个键引用。当我尝试验证实例时,它会产生一个错误,表示密钥超出范围 这些是我的XSD: test1.xsd <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
targetNamespace="test1" xmlns="test1">
<xs:complexType name="Host">
<xs:attribute name="id" type="xs:string"/>
</xs:complexType>
<xs:element name="root">
<xs:complexType>
<xs:all>
<xs:element name="hosts">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="host" type="Host"
/>
</xs:sequence>
</xs:complexType>
<xs:key name="Host-PK">
<xs:selector xpath="host"/>
<xs:field xpath="@id"/>
</xs:key>
</xs:element>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
targetNamespace="test2" xmlns="test2" xmlns:t1="test1">
<xs:import namespace="test1" schemaLocation="test1.xsd"/>
<xs:element name="root">
<xs:complexType>
<xs:all>
<xs:element name="server">
<xs:complexType>
<xs:attribute name="host" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:all>
</xs:complexType>
<xs:keyref name="Host-FK" refer="t1:Host-PK">
<xs:selector xpath="server"/>
<xs:field xpath="@host"/>
</xs:keyref>
</xs:element>
</xs:schema>
test2.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
targetNamespace="test1" xmlns="test1">
<xs:complexType name="Host">
<xs:attribute name="id" type="xs:string"/>
</xs:complexType>
<xs:element name="root">
<xs:complexType>
<xs:all>
<xs:element name="hosts">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="host" type="Host"
/>
</xs:sequence>
</xs:complexType>
<xs:key name="Host-PK">
<xs:selector xpath="host"/>
<xs:field xpath="@id"/>
</xs:key>
</xs:element>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
targetNamespace="test2" xmlns="test2" xmlns:t1="test1">
<xs:import namespace="test1" schemaLocation="test1.xsd"/>
<xs:element name="root">
<xs:complexType>
<xs:all>
<xs:element name="server">
<xs:complexType>
<xs:attribute name="host" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:all>
</xs:complexType>
<xs:keyref name="Host-FK" refer="t1:Host-PK">
<xs:selector xpath="server"/>
<xs:field xpath="@host"/>
</xs:keyref>
</xs:element>
</xs:schema>
我的例子是:
test1.xml
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="test1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="test1 test1.xsd">
<hosts>
<host id="ABC"/>
<host id="DEF"/>
</hosts>
</root>
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:t1="test1" xmlns="test2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="test2 test2.xsd">
<server host="ABC"/>
</root>
<!DOCTYPE root [
<!ENTITY test3 SYSTEM "test3.xml">
]>
<root xmlns="test1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="test1 test1.xsd">
&test3;
</root>
<!DOCTYPE root [
<!ENTITY test3 SYSTEM "test3.xml">
]>
<root xmlns:t1="test1" xmlns="test2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="test2 test2.xsd">
&test3;
<server host="ABC"/>
</root>
test2.xml
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="test1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="test1 test1.xsd">
<hosts>
<host id="ABC"/>
<host id="DEF"/>
</hosts>
</root>
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:t1="test1" xmlns="test2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="test2 test2.xsd">
<server host="ABC"/>
</root>
<!DOCTYPE root [
<!ENTITY test3 SYSTEM "test3.xml">
]>
<root xmlns="test1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="test1 test1.xsd">
&test3;
</root>
<!DOCTYPE root [
<!ENTITY test3 SYSTEM "test3.xml">
]>
<root xmlns:t1="test1" xmlns="test2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="test2 test2.xsd">
&test3;
<server host="ABC"/>
</root>
服务器主机属性是主机ID的关键引用
架构验证期间,test2.xml文件引发以下错误:
错误:[Xerces]标识约束错误:keyref标识
约束“主机FK”是指超出范围的键或唯一键
我怎样才能解决这个问题
我如何从test2.xml引用test1.xml实例?我假设您可以更改这两个XSD,并且您正在使用XSD 1.0 在第一个XSD中,您需要限定XPath元素,因为不固定的元素不属于任何名称空间。照目前情况,你的钥匙不起作用。您可以通过将重复ID添加到
test1
来验证这一点:
<root xmlns="test1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="test1 test1.xsd">
<hosts>
<host id="ABC"/>
<host id="DEF"/>
<host id="DEF"/>
</hosts>
</root>
现在,您可以限定XPath表达式:
<xs:key name="Host-PK">
<xs:selector xpath="t1:host"/>
<xs:field xpath="@id"/>
</xs:key>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
xmlns:t1="test1" targetNamespace="test2"
xmlns="test2" xmlns:t2="test2" >
我还将minOccurs=“0”
添加到hosts
中,这样就可以定义一个只包含服务器的根目录(但这是临时的-我们将在完成之前再次要求它)
现在我们可以在test2.xsd
中引用hosts
元素和Root
类型。我们可以从扩展根
元素的基类型开始,以允许服务器
元素:
<xs:complexType name="NewRoot">
<xs:complexContent>
<xs:extension base="t1:Root">
<xs:sequence>
<xs:element name="server">
<xs:complexType>
<xs:attribute name="host" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
现在test2
中的root
元素是test1
中root
元素的扩展,而host
元素将位于上下文中
由于必须使用XPath来选择服务器元素,因此有必要为test2
的名称空间声明前缀,以便在XPath表达式中使用它:
<xs:key name="Host-PK">
<xs:selector xpath="t1:host"/>
<xs:field xpath="@id"/>
</xs:key>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
xmlns:t1="test1" targetNamespace="test2"
xmlns="test2" xmlns:t2="test2" >
这是重构后的最后一个test2.xsd:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
targetNamespace="test1"
xmlns="test1"
xmlns:t1="test1">
<xs:complexType name="Host">
<xs:attribute name="id" type="xs:string"/>
</xs:complexType>
<xs:complexType name="Root">
<xs:sequence>
<xs:element ref="hosts" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:element name="root" type="Root" />
<xs:element name="hosts">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="host" type="Host"/>
</xs:sequence>
</xs:complexType>
<xs:key name="Host-PK">
<xs:selector xpath="t1:host"/>
<xs:field xpath="@id"/>
</xs:key>
</xs:element>
</xs:schema>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
targetNamespace="test2"
xmlns="test2"
xmlns:t2="test2"
xmlns:t1="test1">
<xs:import namespace="test1" schemaLocation="test1.xsd"/>
<xs:complexType name="NewRoot">
<xs:complexContent>
<xs:extension base="t1:Root">
<xs:sequence>
<xs:element name="server">
<xs:complexType>
<xs:attribute name="host" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="root" type="t2:NewRoot">
<xs:key name="Host-PK">
<xs:selector xpath="t1:hosts/t1:host"/>
<xs:field xpath="@id"/>
</xs:key>
<xs:keyref name="Host-FK" refer="Host-PK">
<xs:selector xpath="t2:server"/>
<xs:field xpath="@host"/>
</xs:keyref>
</xs:element>
</xs:schema>
你可以试试看。除非host
是ABC
或DEF
,否则它不会验证
您可能还希望将hosts
子树保存在一个单独的文件中,并将其导入到两个XML实例中。实现这一点的本机方法是声明DTD实体。首先将您的主机
放入一个文件(test3.xml):
test2.xml
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="test1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="test1 test1.xsd">
<hosts>
<host id="ABC"/>
<host id="DEF"/>
</hosts>
</root>
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:t1="test1" xmlns="test2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="test2 test2.xsd">
<server host="ABC"/>
</root>
<!DOCTYPE root [
<!ENTITY test3 SYSTEM "test3.xml">
]>
<root xmlns="test1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="test1 test1.xsd">
&test3;
</root>
<!DOCTYPE root [
<!ENTITY test3 SYSTEM "test3.xml">
]>
<root xmlns:t1="test1" xmlns="test2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="test2 test2.xsd">
&test3;
<server host="ABC"/>
</root>
&测试3;
现在,您可以将minOccurs=“0”
放回test1.xsd中的hosts
声明中,以确保它始终存在。您可以更改父xsd吗?