给出以下两种模式
(根)
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:someNs="first"
xmlns:someOtherNs="second"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="unqualified"
attributeFormDefault="unqualified"
version="1.0"
targetNamespace="first">
<xsd:import namespace="second" schemaLocation="./child.xsd" />
<xsd:element name="employee" type="someNs:fullpersoninfo" />
<xsd:complexType name="personinfo">
<xsd:sequence>
<xsd:element name="firstname" type="xsd:string" />
<xsd:element name="lastname" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="fullpersoninfo">
<xsd:complexContent>
<xsd:extension base="someNs:personinfo">
<xsd:sequence>
<xsd:element name="address" type="xsd:string" />
<xsd:element name="city" type="xsd:string" />
<xsd:element name="country" type="xsd:string" />
<xsd:group ref="someOtherNs:Child" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:schema>
和(孩子)
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="someId-1"
targetNamespace="second"
elementFormDefault="qualified"
xmlns:someOtherNs="second"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="second">
<xs:element name="ChildElement" type="ChildElement"
nillable="false" />
<xs:complexType name="ChildElement">
<xs:sequence>
<xs:element name="firstname" type="xs:string" />
<xs:element name="lastname" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:group name="Child">
<xs:sequence>
<xs:element ref="ChildElement" minOccurs="0" maxOccurs="1" />
<xs:any processContents="lax" minOccurs="0"
maxOccurs="unbounded"
namespace="##other" />
</xs:sequence>
</xs:group>
</xs:schema>
当孩子使用elementFormDefault="qualified"
而root使用elementFormDefault="unqualified"
时,不应出现唯一的粒子归因。但是,当通过Java的xjc运行时,不可能使用生成的类,因为类上的注释似乎不够 - 至少看起来如此。如何避免UPA?
有问题的错误如下:
org.xml.sax.SAXParseException; lineNumber:8; columnNumber:41; cos-nonambig:“second”:ChildElement和WC [## other:“first”](或来自其替换组的元素)违反“Unique Particle Attribution”。在针对此模式进行验证期间,将为这两个粒子创建歧义。
答案 0 :(得分:3)
引用的错误消息表明架构处理器正在将<xs:any namespace="##other" .../>
解释为允许任何不在命名空间first
中的元素。也就是说,它将组引用视为一个简单的宏扩展,然后在根模式文档的上下文中创建模型组组件(其中##other
将引用除目标命名空间之外的任何命名空间{ {1}}),而不是在子模式文档的上下文中创建它们(其中first
将引用目标名称空间##other
以外的任何名称空间。)
可能会出现section 3.10.2 of the XSD 1.0 spec要求在child.xsd上下文中解释second
的情况:当##other
时,通配符上的{namespace constraint}属性的值组件被描述为“一对namespace="##other"
和not
祖先元素信息项的targetNamespace [attribute]的实际值(如果存在),否则·缺席·” - 对于{{ child.xsd中的1}}元素,该targetNamespace属性的值为<schema>
,而不是xs:any
。
一个案例可能是另一种方式:规范也很清楚,在组件级别看不到对命名模型组的引用,本地元素声明的范围由模型组的位置决定参考,而不是模型组定义的位置等等。在这种情况下,XSD规范可能看起来似乎是非理性的,这意味着second
这里不应该有解释“除{{之外的任何命名空间1}}”。
总的来说,我倾向于第一种解释,但我非常怀疑有可能说服你的工具的创造者改变他们对规范的解释:扩展命名模型组的规则太混乱了并且涉及过多的挥手以轻易说服任何人他们的解释是错误的。
[糟糕。以下所谓的“解决方法”根本不是一种解决方法:它只是另一种更清晰的方式来引出处理器当前所展示的行为。对不起。]
一种解决方法:将命名模型组声明添加到根模式文档,并引用该模型,而不是child.xsd中的模型。所以将它添加到根模式文档:
first
并从
更改参考##other
到
first
[非工作'解决方法的结束'。现在,让我们再试一次。]
解决问题的一种方法是,如果您真的希望您的工具将<xs:group name="Child">
<xs:sequence>
<xs:element ref="someOtherNs:ChildElement"
minOccurs="0"
maxOccurs="1" />
<xs:any processContents="lax"
minOccurs="0"
maxOccurs="unbounded"
namespace="##other" />
</xs:sequence>
</xs:group>
类型中的通配符解释为允许任何不在<xsd:group ref="someOtherNs:Child" />
命名空间中的元素,那么将移动类型{ {1}}进入<xsd:group ref="someNs:Child" />
命名空间。要在fullpersoninfo
命名空间中保留second
等,请使用fullpersoninfo
命名空间中的模型组定义模型组:
second
在address
命名空间中声明first
:
first
以通常的方式参考<xs:group name="additional-person-info">
<xs:sequence>
<xs:element ref="address" ... />
...
声明中的fullpersoninfo
:
second
如果您确定不希望这样的元素有效,则需要采用不同的方法:
<xsd:complexType name="fullpersoninfo">
<xsd:complexContent>
<xsd:extension base="someNs:personinfo">
<xsd:sequence>
<xsd:group ref="someNs:additional-person-info"/>
<xsd:group ref="someOtherNs:Child" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
如果通配符匹配fullpersoninfo
命名空间中没有的任何内容,您可能会认为您确实更喜欢它 - 但在这种情况下,employee
与通配符匹配,您无需提及它在内容模型中。
您可能决定要匹配的内容是当前版本的架构中未声明的内容 - 但为此,您需要在工具中使用XSD 1.1感知。如果您有1.1意识,那么您获得的内容模型将不会被拒绝(尽管它仍然可能会让您感到惊讶的解释)。