我想要一个包含内容或某个属性但不同时包含两者的元素。 元素可以如下所示:
<Location ref="blah"/>
或者这个:
<Location> <aaaLocation>...</aaaLocation> <Location>
但不是这样的:
<Location ref="blah"> <aaaLocation>...</aaaLocation> <Location>
我尝试了一些变体:
<xs:complexType name="FatherOfLocatiion">
<xs:choice>
<xs:element name="Location">
<xs:complexType>
<xs:sequence>
<xs:element name ="aaaLocation" type="Alocation"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Location">
<xs:complexType>
<xs:attribute name="ref" type="xs:string" />
</xs:complexType>
</xs:element>
</xs:choice>
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>
模式在XML spy等工具中有效,但当我尝试使用jaxb从中生成对象时,我收到以下错误:
模型组中会出现名称为“位置”且名称不同的多个元素。
还有其他方法可以强制执行吗?
答案 0 :(得分:4)
有一种方法可以在XSD 1.0中实现,它涉及使用xsi:type属性; xsi:type是一个XML属性,但是,支持XSD的XML处理器会根据您的需要对它进行不同的处理。 (为了完整起见,这种方法是XSD 1.1中替代类型的前身,另一种实现您想要的方式。)
鉴于以下XSD 1.0:
<?xml version="1.0" encoding="utf-8" ?>
<!-- XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com) -->
<xsd:schema elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Location"/>
<xsd:complexType name="LocationWithRef">
<xsd:attribute name="ref" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="LocationWithContent">
<xsd:sequence>
<xsd:element name="a"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
以下XML有效,但没有其他组合;属性:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<Location xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="LocationWithRef" ref="a"/>
使用元素:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<Location xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="LocationWithContent"><a/></Location>
以上内容足以模拟您为XML世界指明的内容;但是,对于XSD代码绑定技术,你需要采取额外的步骤使其友好,就像JAXB(或.NET)。问题是将它们与抽象基类型(下面是ALocation)链接起来。
<?xml version="1.0" encoding="utf-8" ?>
<!-- XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com) -->
<xsd:schema elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Location" type="ALocation"/>
<xsd:complexType name="ALocation" abstract="true"/>
<xsd:complexType name="LocationWithRef">
<xsd:complexContent>
<xsd:extension base="ALocation">
<xsd:attribute name="ref" type="xsd:string" use="required"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="LocationWithContent">
<xsd:complexContent>
<xsd:extension base="ALocation">
<xsd:sequence>
<xsd:element name="a"/>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:schema>
上述优势在于它提供了你所问的内容(唉,xsi:类型可能不适合你或其他人,喜欢)基于几乎所有XSD处理器都支持的技术那里。
不幸的是,XSD 1.1的支持是非常有限的,如果我不得不猜测,它需要一段时间才能得到JAXB的支持(你似乎对它感兴趣),更不用说其他XSD代码绑定了解决方案...
答案 1 :(得分:1)
使用XSD 1.0无法实现此目的,但您可以使用 XSD 1.1 。
要告诉您的解析器您的XSD是1.1,请将这些属性添加到xs:schema
元素:
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" vc:minVersion="1.1"
如果您的解析器支持XSD 1.1,它将理解断言,您可以使用XPath来表达您的规则。
在此XSD文档中:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" vc:minVersion="1.1">
<xs:element name="FatherOfLocation" type="FatherOfLocation"/>
<xs:complexType name="FatherOfLocation">
<xs:sequence>
<xs:element name="Location" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name ="aaaLocation" type="xs:string" minOccurs="0"/>
</xs:sequence>
<xs:attribute name="ref" type="xs:string" use="optional"/>
<xs:assert test="(@ref and not(aaaLocation)) or (not(@ref) and aaaLocation)"></xs:assert>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
ref
属性和aaaLocation
元素都是可选的,但assert
声明了一个限制它的规则(在complexType
的上下文中使用XPath):
(@ref and not(aaaLocation)) or (not(@ref) and aaaLocation)
因此它将验证:
<Location ref="blah"/>
和
<Location> <aaaLocation>...</aaaLocation> </Location>
但不验证
<Location ref="blah"> <aaaLocation>...</aaaLocation> </Location>
或
<Location></Location>
答案 2 :(得分:0)
唉,您希望根据其中一个属性限制元素的内容。这可以使用其他模式语言(如Relax NG),但不能使用W3C XML Schema。奇怪的是XML Spy没有引起任何错误。
通常的解决方法是使用2个不同的元素名称,例如Location
和LocationWithRef
。