是否可以使用任意名称但具有特定属性来定义XSD元素
我想根据模式验证自定义XML文档。 该文档将包括一个包含任意数量元素的结构,每个元素都有一个特定属性。大概是这样的:是否可以使用任意名称但具有特定属性来定义XSD元素,xsd,schema,complextype,Xsd,Schema,Complextype,我想根据模式验证自定义XML文档。 该文档将包括一个包含任意数量元素的结构,每个元素都有一个特定属性。大概是这样的: <Root xmlns="http://tns"> <Records> <FirstRecord attr='whatever'>content for first record</FirstRecord> <SecondRecord attr='whatever'>content for first
<Root xmlns="http://tns">
<Records>
<FirstRecord attr='whatever'>content for first record</FirstRecord>
<SecondRecord attr='whatever'>content for first record</SecondRecord>
...
<LastRecord attr='whatever'>content for first record</LastRecord>
</Records>
</Root>
...
<xs:element minOccurs="1" maxOccurs="1" name="Records">
<xs:complexType>
<xs:sequence>
<xs:any/>
</xs:sequence>
<xs:assert
test="every $child in * satisfies $child/@attr"/>
<xs:assert
test="not(*/*)"/>
</xs:complexType>
</xs:element>
...
<xs:element name="Root">
<xs:complexType>
<xs:sequence>
<xs:element name="Records">
<xs:complexType>
<xs:sequence>
<xs:element name="Record"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="RecordType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="attr"
type="xs:string"
use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:element name="Record"
type="RecordType"
abstract="true"/>
<Root xmlns="http://tns">
<Records>
<Record
alternate-name="FirstRecord"
attr='whatever'>content for first record</Record>
<Record
alternate-name="SecondRecord"
attr='whatever'>content for first record</Record>
...
<Record
alternate-name="LastRecord"
attr='whatever'>content for first record</Record>
</Records>
</Root>
第一条记录的内容
第一条记录的内容
...
第一条记录的内容
XML文档的作者可以包含任意数量的记录,每个记录都有自己选择的任意名称。如何根据XML模式对此进行验证
我已尝试在架构中指定适当的结构类型,但不知道如何在适当的位置引用它:
<xs:schema xmlns="http://tns" targetNamespace="http://tns" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="RecordType"> <!-- This is my record type -->
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="attr" type="xs:string" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:element name="Root">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="Records">
<!-- This is where records should go -->
<xs:complexType />
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
我想单用XSD是不可能的 当你说 任意数量的记录,每个记录都有自己选择的任意名称 这迫使我们使用
元素,但是!将元素声明为any
不允许验证其下的属性
所以。。答案是否定的 您所描述的东西在XSD 1.1中是可能的,在XSD 1.0中也可能有类似的东西,这并不是说它是一种可取的设计 在XML词汇表中,元素类型通常传递有关信息类型的相关信息,在大多数XML模式语言中,用于驱动验证的是元素类型的名称;您描述的设计(有人会说)有点像问我是否可以用Java定义一个对象类,或者用C定义一个结构,它遵守成员可以有任意名称的约束,只要其中一个是值为42的整数。这或许是可能的,但大多数有经验的设计师都会强烈感觉到,这几乎肯定不是解决任何正常问题的正确方法 另一方面,在系统中做一些不寻常和尴尬的事情有时有助于学习如何有效地使用系统。(你从来都不知道一个系统,我的一个朋友曾经说过,直到你彻底滥用它。)所以我的回答有两个部分:如何尽可能接近XSD中指定的设计,以及你可以考虑的替代方案。 在XSD 1.1中指定所需语言的最简单方法是在Records元素上定义一个断言,声明(1)记录的每个子项都有一个“attr”属性,并且(2)记录的任何子项都没有子项。您将有如下内容:
<Root xmlns="http://tns">
<Records>
<FirstRecord attr='whatever'>content for first record</FirstRecord>
<SecondRecord attr='whatever'>content for first record</SecondRecord>
...
<LastRecord attr='whatever'>content for first record</LastRecord>
</Records>
</Root>
...
<xs:element minOccurs="1" maxOccurs="1" name="Records">
<xs:complexType>
<xs:sequence>
<xs:any/>
</xs:sequence>
<xs:assert
test="every $child in * satisfies $child/@attr"/>
<xs:assert
test="not(*/*)"/>
</xs:complexType>
</xs:element>
...
<xs:element name="Root">
<xs:complexType>
<xs:sequence>
<xs:element name="Records">
<xs:complexType>
<xs:sequence>
<xs:element name="Record"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="RecordType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="attr"
type="xs:string"
use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:element name="Record"
type="RecordType"
abstract="true"/>
<Root xmlns="http://tns">
<Records>
<Record
alternate-name="FirstRecord"
attr='whatever'>content for first record</Record>
<Record
alternate-name="SecondRecord"
attr='whatever'>content for first record</Record>
...
<Record
alternate-name="LastRecord"
attr='whatever'>content for first record</Record>
</Records>
</Root>
“processContents”属性的值可以更改为“strict”或“skip”或保持为“lax”,具体取决于您是否希望验证(和声明)FirstRecord、SecondRecord等。这是一个非常详细的答案,非常感谢。据我所知,在.net世界中,我没有访问XSD1.1兼容解析器的权限,因此无法对其进行测试。至于XSD1.0解决方案,这很接近,但还不完全,所以我不能使用它。然后,它将处理一个简单的非类型化序列。额外的验证必须在应用程序级别执行。感谢您提供的其他建议,尽管在我的案例中没有这样做,这包括实现一种基本的插件机制,即每个插件将其属性保存在PropertyBag中,并序列化为XML结构。在这个场景中,“记录”被替换为“属性”,而“@attr”被替换为“@vt”,以指定属性的“变体类型”。每个插件可以有任意数量的属性,每个属性都可以是@vt属性指定的任何类型。解析器托管在我的框架中,而不是每个插件中。。。因此需要一个固定结构的XSD 1.0解决方案:比声明不可能要好得多:)看起来XSD 1.0确实不可能。根据C.M.Sperberg McQueen的回答,XSD 1.1似乎是可能的,尽管我无法在.net世界中验证,因为据我所知,微软的解析器不支持它。@MaximeLabelle.net不支持XSD 1.1!但是Saxon支持,并且.Net支持Saxon!