我需要创建一个XSD来验证以下XML:
<?xml version="1.0" encoding="UTF-8"?>
<thing:cardAuthRequestResponse
xmlns:thing="http://www.thing.com/thing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<thing:request xsi:type="thing:GiftCardBalanceRequest" />
</thing:cardAuthRequestResponse>
我尝试了各种在线XSD生成器和验证器(例如https://www.freeformatter.com/xml-validator-xsd.html&amp; https://www.freeformatter.com/xsd-generator.html),但没有人生成一个XSD来验证XML,但有各种错误。问题出在名称空间类型属性:xsi:type
以下内容将验证(xsi
命名空间已从type
属性中删除):
INPUT:
<?xml version="1.0" encoding="UTF-8"?>
<thing:cardAuthRequestResponse
xmlns:thing="http://www.thing.com/thing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<thing:request type="thing:GiftCardBalanceRequest" />
</thing:cardAuthRequestResponse>
XSD
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.thing.com/thing" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="cardAuthRequestResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="request">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:QName" name="type"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
我是否可以更改XSD以使用namespaced type属性验证XML,或者是否存在基本上与XML无关的内容?
答案 0 :(得分:0)
似乎您的xml正在尝试创建xsd类型的动态列表,然后包含内容并且可以进行验证。这与xml没有关系,但如果自动生成的模式可以理解这个目标,我会感到惊讶。
我重新设计了一些命名空间,让它们实际链接并协同工作,以创建一个可能看起来如何的示例。
XSD - 只需定义您有一个cardAuthRequestResponse
,其中包含任意数量的request
元素。这些可以是xs:anyType
。
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.enactor.com/retail">
<xs:element name="cardAuthRequestResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="request" type="xs:anyType" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="GiftCardBalanceRequest">
</xs:complexType>
<xs:complexType name="AgeRequest">
<xs:sequence>
<xs:element name="age">
<xs:simpleType>
<xs:restriction base="xs:nonNegativeInteger" />
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
这将允许您验证此xml
<?xml version="1.0" encoding="UTF-8"?>
<retail:cardAuthRequestResponse
xmlns:retail="http://www.enactor.com/retail"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<retail:request xsi:type="retail:GiftCardBalanceRequest" numRequests="2" />
<retail:request xsi:type="retail:AgeRequest" numRequests="2">
<retail:age>2</retail:age>
</retail:request>
</retail:cardAuthRequestResponse>
现在,您可以看到我现在编写的AgeRequest
允许您验证这些特定元素。
现在这个方法有1个缺点,request
扩展了xs:anyType
。这意味着你可以放<retail:request><foobar/>2</retail:request>
,它也有效。但是,如果您对样本进行了简化以便简化,那么您可能需要修复它。
这会使您的xsd更强类型,并限制request
可以定义的类型。它允许您创建所有request
元素的基本属性和元素要求。例如:
XSD - 只需定义您有一个cardAuthRequestResponse
,其中包含任意数量的request
元素。这些可以是retail:baseRetailRequest
。
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:retail="http://www.enactor.com/retail"
targetNamespace="http://www.enactor.com/retail">
<xs:element name="cardAuthRequestResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="request" type="retail:baseRetailRequest" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="baseRetailRequest">
<xs:attribute name="numRequests" type="xs:nonNegativeInteger" use="required"></xs:attribute>
</xs:complexType>
<xs:complexType name="GiftCardBalanceRequest">
<xs:complexContent>
<xs:extension base="retail:baseRetailRequest">
<xs:sequence></xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="AgeRequest">
<xs:complexContent>
<xs:extension base="retail:baseRetailRequest">
<xs:sequence>
<xs:element name="age">
<xs:simpleType>
<xs:restriction base="xs:nonNegativeInteger" />
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
现在每个<request>
都需要为其定义numRequests
属性。如果您有一个必须填写的基本请求,这可能很有用。例如:
<?xml version="1.0" encoding="UTF-8"?>
<retail:cardAuthRequestResponse
xmlns:retail="http://www.enactor.com/retail"
xmlns:thing="http://www.thing.com/thing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<retail:request xsi:type="thing:GiftCardBalanceRequest" numRequests="2" />
<retail:request xsi:type="thing:AgeRequest" numRequests="2">
<thing:age>2</thing:age>
</retail:request>
</retail:cardAuthRequestResponse>
答案 1 :(得分:0)
首先,您的XSD不是有效的架构,因为xs:attribute的name属性必须是NCName(因此xsi:type
无效)。
通常,如果要允许与模式的targetNamespace不同的名称空间中的属性,您可以在具有自己的targetNamespace的不同模式文档中声明它,导入该模式文档,并使用“ref”引用该属性“而不是”名字“。
但是xsi:type
是特殊的:它隐含地声明并隐式允许任何元素。因此,您只需从架构中删除对xsi:type
的引用即可。
下一个问题是您的实例文档位于命名空间http://www.thing.com/thing
中,而您的架构定义了命名空间http://www.enactor.com/retail
。我不确定这是在发布您的问题时发生的简单复制/粘贴错误,还是您从根本上无法理解命名空间在确保模式有效性方面的重要性。
如果我解决了这个问题,我就会遗漏一个错误:
test.xml第6行第62列的验证错误: FORG0001:xsi:type属性中指定的未知类型{thing:GiftCardBalanceRequest}
这是因为xsi:type
的语义要求其值是模式中声明的类型的名称,并且您的模式不包含此类型。
哦,没有必要尝试将xsi:type的声明写入任何文档的模式;模式验证器使用它来为元素选择类型(具体来说,覆盖默认类型赋值),但不会根据元素的声明进行验证。为xsi命名空间编写模式文档并不是错误,但任何符合标准的处理器都不会使用它。
答案 2 :(得分:0)
...... XML有什么根本无效的吗?
没有XML实例可以构建一个有效的模式。从来没有&#34;从根本上无效&#34; XML文档。
在目前的情况下,您应该花一两个小时来阅读xsi:type属性的使用;它用于指定用于验证的模式中存在的类型的名称,以覆盖分配给该元素的默认类型。
使实例有效所需的最低要求是具有
的模式{http://www.thing.com/thing}cardAuthRequestResponse
,允许有效元素实例包含名为{http://www.thing.com/thing}request
的单个元素作为内容; {http://www.thing.com/thing}request
的声明,它为其指定了一些命名类型,不会阻止派生类型的派生;和{http://www.thing.com/thing}GiftCardBalanceRequest
的类型的顶级类型定义,该类型派生自第2项中指定给元素{http://www.thing.com/thing}request
的类型。例如:
<xsd:schema targetNamespace="http://www.thing.com/thing"
xmlns:thing="http://www.thing.com/thing"
xmlns:xsd="..."
... >
<xsd:element name="cardAuthRequestResponse"/>
<xsd:element name="request"/>
<xsd:type name="GiftCardBalanceRequest"/>
</
用于生成模式的工具可能不适用于包含xsi:type属性的实例,这并不奇怪:xsi:type用于指向现有模式中的类型,如果模式已存在,则工具可能很好奇为什么有人在运行它。
如果您自己创建XML,为什么使用xsi:type?
如果您从其他人那里收到XML,您是否询问了架构文档的位置?