我需要创建一个验证XML文档树结构的XML模式。我不确切知道树的出现次数或深度级别。
XML示例:
<?xml version="1.0" encoding="utf-8"?>
<node>
<attribute/>
<node>
<attribute/>
<node/>
</node>
</node>
哪种验证方法最好?递归?
答案 0 :(得分:66)
如果您需要递归类型声明,这里有一个可能有用的示例:
<xs:schema id="XMLSchema1"
targetNamespace="http://tempuri.org/XMLSchema1.xsd"
elementFormDefault="qualified"
xmlns="http://tempuri.org/XMLSchema1.xsd"
xmlns:mstns="http://tempuri.org/XMLSchema1.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:element name="node" type="nodeType"></xs:element>
<xs:complexType name="nodeType">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="node" type="nodeType"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
正如您所看到的,这定义了一个递归模式,只有一个名为“node”的节点可以根据需要进行深入。
答案 1 :(得分:39)
XSD确实允许元素的递归。这里is a sample for you
<xsd:element name="section">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="title"/>
<xsd:element ref="para" maxOccurs="unbounded"/>
<xsd:element ref="section" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
正如您所看到的,section元素包含一个类型为section的子元素。
答案 2 :(得分:0)
其他解决方案对于使根元素递归非常有用。但是,为了使非根元素递归而不在该过程中将其转换为有效的根元素,需要一种略有不同的方法。
假设您要定义一种XML消息格式,以便在分布式应用程序的节点之间交换结构化数据。它包含以下元素:
<message>
-根元素; <from>
-消息的来源; <to>
-邮件的目的地; <type>
-消息中编码的数据结构类型; <data>
-消息中包含的数据。为了支持复杂的数据类型,<data>
是一个递归元素。这样可以编写以下消息,以发送例如向飞行的无人机发送geometry_msgs/TwistStamped
消息,指定其线性和角速度(即旋转速度):
<?xml version="1.0" encoding="utf-8"?>
<message xmlns="https://stackoverflow.com/message/1.0.0">
<from>controller:8080</from>
<to>drone:8080</to>
<type>geometry_msgs/TwistStamped</type>
<data name="header">
<data name="seq">0</data>
<data name="stamp">
<data name="sec">1</data>
<data name="nsec">0</data>
</data>
<data name="frame_id">base_link</data>
</data>
<data name="twist">
<data name="linear">
<data name="x">1.0</data>
<data name="y">0</data>
<data name="z">1.0</data>
</data>
<data name="angular">
<data name="x">0.3</data>
<data name="y">0</data>
<data name="z">0</data>
</data>
</data>
</message>
我们可以轻松地编写XML模式来验证这种格式:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="https://stackoverflow.com/message/1.0.0"
elementFormDefault="qualified"
xmlns="https://stackoverflow.com/message/1.0.0"
>
<xs:element name="data">
<xs:complexType mixed="true">
<xs:sequence>
<xs:element ref="data" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="message">
<xs:complexType>
<xs:sequence>
<xs:element name="from" type="xs:string"/>
<xs:element name="to" type="xs:string"/>
<xs:element name="type" type="xs:string"/>
<xs:element ref="data" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
上述架构的问题在于它使<data>
成为根元素,这意味着它也验证了下面的文档:
<?xml version="1.0" encoding="utf-8"?>
<data xmlns="https://stackoverflow.com/message/1.0.0" name="twist">
<data name="header">
<data name="seq">0</data>
<data name="stamp">
<data name="sec">1</data>
<data name="nsec">0</data>
</data>
<data name="frame_id">base_link</data>
</data>
<data name="twist">
<data name="linear">
<data name="x">1.0</data>
<data name="y">0</data>
<data name="z">1.0</data>
</data>
<data name="angular">
<data name="x">0.3</data>
<data name="y">0</data>
<data name="z">0</data>
</data>
</data>
</data>
为了避免这种副作用,我们首先定义一个<data>
类型,然后再定义一个data
类型,而不是直接在全局级别上定义data
元素在message
中输入:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="https://stackoverflow.com/message/1.0.0"
elementFormDefault="qualified"
xmlns="https://stackoverflow.com/message/1.0.0"
>
<xs:complexType name="data" mixed="true">
<xs:sequence>
<xs:element name="data" type="data" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>
<xs:element name="message">
<xs:complexType>
<xs:sequence>
<xs:element name="from" type="xs:string"/>
<xs:element name="to" type="xs:string"/>
<xs:element name="type" type="xs:string"/>
<xs:element name="data" type="data" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
请注意,我们最终不得不两次定义<data>
元素-一次在data
类型内,再一次在<element>
内部内,但除了一点重复的工作外,这没有任何意义