我有几个xml文件,但我只提供一个和验证它所依据的xsd。让我先描述一下问题。我在VS2010中编辑这些文件,VS运行时解析器在编辑xml文件时没有显示任何错误。然后,当我运行一个php命令行脚本,该脚本加载xml文件并根据xml模式对其进行验证时,它以一个exception结束,它说
警告:DOMDocument::schemaValidate():元素'Element':找不到keyref'elementRef'的键序列[answers']的匹配项。
但是,我确实看不出xsd文件中有任何错误。
Xml文件:
<domain xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Answer" namespace="CustomSurveys" xsi:noNamespaceSchemaLocation="../../xsd/domain.xsd">
<entities>
<entity name="Answer" main="true" schema="answers"/>
</entities>
<bindings>
</bindings>
<key>
<element entity="answers" property="question_option_id"/>
<element entity="answers" property="survey_voter_id"/>
</key>
</domain>
xsd文件中的Xml架构:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="domain">
<xs:complexType>
<xs:sequence>
<xs:element name="entities">
<xs:complexType>
<xs:sequence>
<xs:element name="entity" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="name" type="xs:string" use="required" id="entityName" />
<xs:attribute name="main" type="xs:boolean" use="optional" default="false" />
<xs:attribute name="schema" type="xs:string" use="required" id="schemaName" />
</xs:complexType>
</xs:element>
<xs:element name="multientity" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="schema" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="bindings" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="bind" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="referenced">
<xs:complexType>
<xs:attribute name="entity" type="xs:string" use="required" />
<xs:attribute name="property" type="xs:string" use="required" />
</xs:complexType>
<xs:keyref name="referencedRef" refer="entityId">
<xs:selector xpath="." />
<xs:field xpath="@entity" />
</xs:keyref>
</xs:element>
</xs:sequence>
<xs:attribute name="entity" type="xs:string" use="required" />
<xs:attribute name="property" type="xs:string" use="required" />
</xs:complexType>
<xs:keyref name="bindRef" refer="entityId">
<xs:selector xpath="." />
<xs:field xpath="@entity" />
</xs:keyref>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="key">
<xs:complexType>
<xs:sequence>
<xs:element name="element" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="entity" type="xs:string" use="required" />
<xs:attribute name="property" type="xs:string" use="required" />
</xs:complexType>
<xs:keyref name="elementRef" refer="entityId">
<xs:selector xpath="." />
<xs:field xpath="@entity" />
</xs:keyref>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="namespace" type="xs:string" use="required" />
</xs:complexType>
<xs:key name="entityId">
<xs:selector xpath="./entities/entity|./entities/multientity" />
<xs:field xpath="@schema" />
</xs:key>
</xs:element>
</xs:schema>
我找到了一个解决方案,我必须在最后定义根元素中的所有键和keyrefs。
下面是新的xsd文件:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="domain">
<xs:complexType>
<xs:sequence>
<xs:element name="entities">
<xs:complexType>
<xs:sequence>
<xs:element name="entity" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="name" type="xs:string" use="required" id="entityName" />
<xs:attribute name="main" type="xs:boolean" use="optional" default="false" />
<xs:attribute name="schema" type="xs:string" use="required" id="schemaName" />
</xs:complexType>
</xs:element>
<xs:element name="multientity" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="schema" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="bindings" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="bind" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="referenced">
<xs:complexType>
<xs:attribute name="entity" type="xs:string" use="required" />
<xs:attribute name="property" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="entity" type="xs:string" use="required" />
<xs:attribute name="property" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="key">
<xs:complexType>
<xs:sequence>
<xs:element name="element" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="entity" type="xs:string" use="required" />
<xs:attribute name="property" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="namespace" type="xs:string" use="required" />
</xs:complexType>
<xs:key name="entityId">
<xs:selector xpath="./entities/entity|./entities/multientity" />
<xs:field xpath="@schema" />
</xs:key>
<xs:keyref name="elementRef" refer="entityId">
<xs:selector xpath="./key/element" />
<xs:field xpath="@entity" />
</xs:keyref>
<xs:keyref name="bindRef" refer="entityId">
<xs:selector xpath="./bindings/bind" />
<xs:field xpath="@entity" />
</xs:keyref>
<xs:keyref name="referencedRef" refer="entityId">
<xs:selector xpath="./bindings/bind/referenced" />
<xs:field xpath="@entity" />
</xs:keyref>
</xs:element>
</xs:schema>
如果可能的话,我建议始终将keyref及其相应的键放在同一级别(在同一元素声明中)。这在理论上是不需要的,但当你不需要的时候,规则会非常复杂,有时甚至违背直觉。(我之所以不告诉你规则是什么,是因为我知道阅读这个区域的规范会伤我的大脑,如果不阅读规范,我不可能记住规则。)