LIST元素派生



在XML学习曲线上,我在使用list元素时遇到了验证问题。我正在尝试创建一个list元素,该元素只允许特定key的值作为成员。

一个小的上下文来帮助你建模接下来的内容。我们有各种各样的SOURCE,每个都有唯一的NAMENAME格式受到simpleType元素中的模式的限制;REFDESTypeNAME的唯一性是由密钥source_key强制实现的。

现在,尝试有效地使用这个source_key来提供相关数据字段的输入限制还没有产生预期的结果。CCD_ 11是这些预期用途字段中的一个,并且是元素CCD_。其目的是使POWERSOURCE能够对SOURCE NAME中的一个或多个进行list,但不能进行MSXML解析。{好吧,欢迎你笑着从地板上爬起来后回来。}是的,这是为一个独立的基于EXCEL 2013的应用程序开发的,没有第三方库。

一个似乎很明显的问题(无论如何对我来说)是REFDESType从两个方向树到POWERSOURCE。一次通过CCD_ 18并且再次通过REFDESList。嗯…

分析错误:keyref'GEN-1 GEN-2 GEN-3 GEN-4'未解析为标识约束的key'{http://www.myCo.com}source_key'

当然,使用list的效用对我来说是显而易见的。现在,如果我能理解这种方式是如何不起作用的话。替代方法也受到欢迎。

ELA.XSD:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://www.myCo.com" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ela="http://www.myCo.com" elementFormDefault="qualified">
<xs:element name="DB">
<xs:complexType>
<xs:sequence>
<xs:element ref="ela:SOURCE" maxOccurs="unbounded"/>
<xs:element ref="ela:MODE" minOccurs="6" maxOccurs="13"/>
</xs:sequence>
</xs:complexType>
<xs:key name="source_key">
<xs:selector xpath="ela:SOURCE"/>
<xs:field xpath="ela:NAME"/>
</xs:key>
</xs:element>
<xs:element name="SOURCE" type="ela:SOURCEType"/>
<xs:element name="NAME" type="ela:REFDESType"/>
<xs:element name="MODE" type="ela:MODEType"/>
<xs:element name="POWERSOURCE" type="ela:REFDESList">
<xs:keyref name="powersource_ref" refer="ela:source_key">
<xs:selector xpath="."/>
<xs:field xpath="."/>
</xs:keyref>
</xs:element>
<xs:simpleType name="REFDESList">
<xs:list itemType="ela:REFDESType"/>
</xs:simpleType>
<xs:simpleType name="REFDESType">
<xs:restriction base="xs:string">
<xs:minLength value="2"/>
<xs:maxLength value="9"/>
<xs:pattern value="[A-Z]([A-Z0-9;&#32;&#45;]){1,8}"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="MODEType">
<xs:sequence>
<xs:element ref="ela:POWERSOURCE"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="SOURCEType" mixed="true">
<xs:sequence>
<xs:element ref="ela:NAME"/>
</xs:sequence>
</xs:complexType>
</xs:schema>

sample.XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ela:DB xmlns:ela="http://www.myCo.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.myCo.com ELA.xsd">
<ela:SOURCE>
<ela:NAME>GEN-1</ela:NAME>
</ela:SOURCE>
<ela:SOURCE>
<ela:NAME>GEN-2</ela:NAME>
</ela:SOURCE>
<ela:SOURCE>
<ela:NAME>GEN-3</ela:NAME>
</ela:SOURCE>
<ela:SOURCE>
<ela:NAME>GEN-4</ela:NAME>
</ela:SOURCE>
<ela:MODE>
<ela:POWERSOURCE>GEN-1 GEN-2 GEN-3 GEN-4</ela:POWERSOURCE>
</ela:MODE>
</ela:DB>

您的keyref表示整个值(即"GEN-1 GEN-2 GEN-3 GEN-4")必须与某个键值匹配。

我认为keyref没有任何方法可以实现与IDREFS类型相同的效果,在IDREFS中,列表中的每个项都必须单独满足完整性约束。为此,您需要使用XSD 1.1断言。

无法将单个列表成员与键匹配,只能将整个列表匹配。在XML文件中,<ela:POWERSOURCE>的值是一个包含四个项目的列表。但是,不存在与该值匹配的<ela:NAME>(即具有相同四个项目的列表)。

模式的另一个问题是xs:keyref引用了在祖先中定义的xs:key,这是不允许的。引用的键必须在同一元素声明中定义,或者在元素的子代中定义。

具有key和keyref的现代解决方案

一个有关键约束的可能解决方案是为每个列表项使用专用元素:

<ela:MODE>
<ela:POWERSOURCE>
<ela:NAME>GEN-1</ela:NAME>
<ela:NAME>GEN-2</ela:NAME>
<ela:NAME>GEN-3</ela:NAME>
<ela:NAME>GEN-4</ela:NAME>
</ela:POWERSOURCE>
</ela:MODE>

在模式中,您可以简单地将REFDESList类型更改为:

<xs:complexType name="REFDESList">
<xs:sequence>
<xs:element ref="ela:NAME" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>

并将keyref移动到与密钥相同的元素:

<xs:element name="DB">
<xs:complexType>
<xs:sequence>
<xs:element ref="ela:SOURCE" maxOccurs="unbounded"/>
<xs:element ref="ela:MODE" minOccurs="1" maxOccurs="13"/>
</xs:sequence>
</xs:complexType>
<xs:key name="source_key">
<xs:selector xpath="ela:SOURCE"/>
<xs:field xpath="ela:NAME"/>
</xs:key>
<xs:keyref name="powersource_ref" refer="ela:source_key">
<xs:selector xpath="ela:MODE/ela:POWERSOURCE/ela:NAME"/>
<xs:field xpath="."/>
</xs:keyref>
</xs:element>

具有ID和IDREFS的旧版解决方案

正如@Michael Kay所提到的,有一个遗留机制使用xs:ID和xs:IDREFS类型。要将它们应用于架构,请删除xs:keyxs:keyref元素,并替换超类型REFDESType:

<xs:simpleType name="REFDESType">
<xs:restriction base="xs:ID"> <!-- Restrict legacy ID type -->
<xs:minLength value="2"/>
<xs:maxLength value="9"/>
<xs:pattern value="[A-Z]([A-Z0-9;&#32;&#45;]){1,8}"/>
</xs:restriction>
</xs:simpleType>

现在,<ela:NAME>元素的值是ID的一个子类型,可以由IDREF或IDREFS:类型的值引用

<xs:element name="POWERSOURCE" type="xs:IDREFS"/> <!-- List of ID references -->

如果使用的工具符合标准,那么调整后的XSD应该验证您的XML文件。但请注意,本标准建议ID和IDREFS仅用于属性,即

<ela:NAME id="GEN-1"/>
...
<ela:POWERSOURCE ref="GEN-1 GEN-2 GEN-3 GEN-4"/>

@Michael Kay,@Meyer;

除非我遗漏了什么(并且事实证明我是),否则IDREFS建议根本不适用于MSXML(除非您完全处理simpleType中的列表元素。)。它在XMLSpy开发工具中运行良好,但一旦试图通过SchemaCollection.Add方法将模式加载到Excel2013中,就会引发此错误。

列表数据类型必须派生自原子数据类型或的并集原子数据类型。

此错误消息似乎与itemType的"已报告"MSXML LIST元素定义相矛盾,后者是…

中定义的内置数据类型或simpleType元素的名称架构(或由指定命名空间指示的另一个架构)。这个包含list元素的simpleType元素派生自列表值指定的简单类型。列表值必须是限定名称(QName)。simpleType元素child和itemType属性是互斥的。

我相信我的模式符合LIST要求。"SOURCENAMEType"是派生LIST simpleType"IDREFListType"的原始simpleType。原始XML:A-Z{1,8}"/>

<xs:simpleType name="IDREFListType">
<xs:list itemType="xs:IDREFS"/>
</xs:simpleType>
<xs:element name="SOURCELIST" type="ela:IDREFListType"/>

实际工作的修订版:我将把它重新写成通用XML,这样它就可以很容易地复制和重复使用。请注意,myLISTType不包含任何xs:list元素,尽管这正是它的工作方式。原因是填充它的原子元素的复数形式,即xs:IDREFS,它已经是Collection元素。在MSXML中,他们显然不需要声明列表元素(在这种情况下),这样他们的解析器就不会将其解释为根据W3C不允许的列表列表。(我的假设是基于广泛的测试。)问题是,我在任何地方都找不到这种细微差别的记录。啊!!!

<xs:schema targetNamespace="http://www.myCo.com" xmlns:pfx="http://www.myCo.com" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="IDNAME" type="pfx:myIDNAMEType" maxOccurs="unbounded"/>
<xs:element name="myLIST" type="pfx:myLISTType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:simpleType name="myIDNAMEType">
<xs:restriction base="xs:ID">
<xs:pattern value="[A-Z]([A-Z0-9;&#32;&#45;]){1,8}"/>
<!-- pattern for illustrative purposes only, not req'd -->
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="myLISTType">
<xs:restriction base="xs:IDREFS">
<xs:minLength value="1"/>
<xs:maxLength value="4"/>
<!-- min/max for illustrative purposes only, not req'd -->
<!-- defines limits for # of members permitted in list -->
</xs:restriction>
</xs:simpleType>
</xs:schema>

XML:

<pfx:IDNAME>BOGUS-1</pfx:IDNAME>
<pfx:IDNAME>BOGUS-2</pfx:IDNAME>
<pfx:IDNAME>BOGUS-3</pfx:IDNAME>
<pfx:IDNAME>BOGUS-4</pfx:IDNAME>
<pfx:myLIST>BOGUS-1 BOGUS-2 BOGUS-3 BOGUS-4</pfx:myLIST>

验证检测到以下错误(基于限制方面,如图所示):

  • 超过了列表成员的数量;参见最小/最大限制方面
  • 未被认定为合法成员的名单成员,例如BOGUS-9不在IDNAME集

最新更新