Reputation: 12710
I'd like to build a XSD for a tree of string key-value pairs. Something to fit this:
<entry>
<key>root</key>
<entry key="name">john</entry>
<entry key="address">
<entry key="street">Rou de Flon 1</entry>
<entry key="city">Lausanne</entry>
</entry>
</entry>
I didn't manage to get this (I want to use xsd:string, and not xsd:anyType)
This alternative pattern:
<entry>
<key>root</key>
<entry>
<key>name</key>
<value>john</value>
</entry>
<entry>
<key>address</key>
<entry>
<key>street</key>
<value>Rou de Flon 1</value>
</entry>
<entry>
<key>city</key>
<value>Lausanne</value>
</entry>
</entry>
</entry>
can be done with:
<xsd:complexType name="Entry">
<xsd:sequence>
<xsd:element name="key" type="xsd:string"/>
<xsd:choice>
<xsd:element name="value" type="xsd:string"/>
<xsd:element name="entry" maxOccurs="unbounded" type="rbo:Entry"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
but I would prefer to use the first pattern, because it is more compact.
I tried this other XSD:
<xsd:complexType name="ValueEntry">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="key" use="required" type="xsd:string"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
<xsd:complexType name="ListEntry">
<xsd:sequence>
<xsd:element name="entry" maxOccurs="unbounded" type="rbo:ListOrValueEntry"/>
</xsd:sequence>
<xsd:attribute name="key" use="required" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="ListOrValueEntry">
<xsd:sequence>
<xsd:choice>
<xsd:element name="value" type="rbo:ValueEntry"/>
<xsd:element name="entry" type="rbo:ListEntry"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
but it produces more ugly XML:
<listEntry>
<entry>
<value key="name">john</value>
</entry>
<entry>
<entry key="address">
<entry>
<value key="street">Rou de Flon 1</value>
</entry>
<entry>
<value key="city">Lausanne</value>
</entry>
</entry>
</entry>
</listEntry>
So, is there a way to create a XSD for this pattern, without using xsd:anyType?
<entry>
<key>root</key>
<entry key="name">john</entry>
<entry key="address">
<entry key="street">Rou de Flon 1</entry>
<entry key="city">Lausanne</entry>
</entry>
</entry>
ps: please, don't discuss whether you like this pattern or not; that's a nice discussion, but it is not the objective of this post. the objective of this post is to find out how to, if at all possible, write XSD for this XML, without using xsd:anyType.
Upvotes: 1
Views: 11778
Reputation: 31760
You have to used mixed content on your definition for Entry
. Also you need the minOccurs="0".
<xsd:complexType name="Entry" mixed="true">
<xsd:sequence>
<xsd:element name="key" minOccurs="0" type="xsd:string" />
<xsd:element name="entry" minOccurs="0" maxOccurs="unbounded" type="Entry"/>
</xsd:sequence>
<xsd:attribute name="key" type="xsd:string" />
</xsd:complexType>
This allows you to have the exact structure you want.
Upvotes: 0
Reputation: 28951
You should use different tag names for string and non-string elements. Most close structure would be
<entry key="root">
<value key="name">john</value>
<entry key="address">
<value key="street">Rou de Flon 1</value>
<value key="city">Lausanne</value>
</entry>
</entry>
Schema for it:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="entry" type="entryType"/>
<xs:complexType name="entryType">
<xs:choice maxOccurs="unbounded">
<xs:element type="valueType" name="value"/>
<xs:element type="entryType" name="entry"/>
</xs:choice>
<xs:attribute type="xs:string" name="key"/>
</xs:complexType>
<xs:complexType name="valueType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="key"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:schema>
However, it's the XML. More readable will be:
<root>
<name>john</name>
<address>
<street>Rou de Flon 1</street>
<city>Lausanne</city>
</address>
</root>
Upvotes: 3