XML模式中的条件

时间:2012-10-25 14:50:53

标签: xml xsd

考虑以下(设计不佳?)XML文档:

<?xml version="1.0" ?>
<command_result>
<param name="protocol_version" value="3"/>
<param name="player_state" value="navigator"/>
</command_result>

我想要做的是创建一个XML架构(XSD格式),它根据value属性的实际值指定name属性的数据类型。

示例(伪代码):

if (param name = "protocol_version") then (param value type="xs:integer")
if (param name = "player_state") then (param value type="xs:string")

有没有办法在不修改源XML的情况下在模式文件中引入这样的条件语句?我已经查看了各种解决方案,但所有这些解决方案都需要以某种方式更改源(例如,设置xsi:type)。

修改

我目前的架构:

<?xml version="1.0" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="command_result">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="param" minOccurs="2" maxOccurs="unbounded">
                    <xs:complexType>
                        <xs:attribute name="name" type="xs:string" use="required"/>
                        <!-- the following line needs to be modified somehow -->
                        <xs:attribute name="value" type="xs:string" use="optional"/>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

2 个答案:

答案 0 :(得分:2)

我不认为这是可能的。我能想到的唯一方法就是这样:

<schema xmlns="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.example.org/schema"
    xmlns:tns="http://www.example.org/schema" elementFormDefault="qualified">

    <element name="command_result">
        <complexType>
            <sequence>
                <choice>
                    <element name="param" type="tns:protocol_version_type" />
                    <element name="param" type="tns:player_state_type" />
                </choice>
            </sequence>
        </complexType>
    </element>

    <complexType name="protocol_version_type">
        <attribute name="name" type="string" fixed="protocol_version" />
        <attribute name="value" type="integer" />
    </complexType>

    <complexType name="player_state_type">
        <attribute name="name" type="string" fixed="player_state" />
        <attribute name="value" type="string" />
    </complexType>
</schema>

但显然这是不允许的。当我在Eclipse中验证此模式时,它会给我以下错误:

  
      
  • cos-nonambig:“http://www.example.org/schema":param和”http://www.example.org/schema":param(或其替换组中的元素)违反了“Unique Particle”归因”。在针对此模式进行验证期间,将为这两个粒子创建歧义。
  •   
  • cos-element-consistent:类型'#AnonType_command_result'的错误。 模型组中会显示名称为“param”且名称不同的多个元素。
  •   

如您所见,您不能拥有两个名称相同但类型不同的元素。但这正是您的XML所需要的。

编辑:您甚至无法定义更简单的架构:

<element name="command_result">
    <complexType>
        <sequence>
            <element name="param" type="tns:proptocol_version_type" />
            <element name="param" type="tns:type2" />
        </sequence>
    </complexType>
</element>

在此版本中,没有给出<choice>,这意味着您的参数必须以给定的顺序出现。但是,虽然这会删除nonambig错误,但element-consistent错误仍然存​​在。

答案 1 :(得分:1)

如果您有权访问XSD 1.1验证程序,则可以使用条件类型分配根据param属性的值为name元素指定不同的绑定。 (您将绑定它的不同复杂类型主要区别在于为value属性分配不同的类型。)

但总的来说,你是对的:为每个元素使用相同的元素名称是一种设计选择,它简化了一些事情,但代价是试图验证参数。