Is it possible to define an attribute in xsd so that it may have an empty value but is checked to refer to another element when there is a value?
<?xml version="1.0" encoding="UTF-8"?>
<TableStructure xmlns="tmp/TableStructure"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="tmp/TableStructure TableStructure.xsd">
<Column name="a" />
<Column name="b" />
<Column name="c" />
<Range name="r1" fromColumn="a" toColumn="b" /> <!-- works -->
<Range name="r2" fromColumn="a" toColumn="" /> <!-- should work -->
<Range name="r3" fromColumn="a" /> <!-- works -->
<Range name="r4" fromColumn="" toColumn="c" /> <!-- should work -->
<Range name="r5" fromColumn="foo" toColumn="bar" /> <!-- should not and does not work -->
</TableStructure>
I tried the following Schema:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema targetNamespace="tmp/TableStructure" elementFormDefault="qualified"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="tmp/TableStructure"
xmlns:ts="tmp/TableStructure">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"
schemaLocation='http://www.w3.org/2009/01/xml.xsd' />
<xsd:element name="TableStructure">
<xsd:complexType>
<xsd:sequence minOccurs="1" maxOccurs="1">
<xsd:element ref="Column" maxOccurs="unbounded" minOccurs="0" />
<xsd:element ref="Range" maxOccurs="unbounded" minOccurs="0" />
</xsd:sequence>
</xsd:complexType>
<xsd:key name="columnName-key">
<xsd:selector xpath="./ts:Column" />
<xsd:field xpath="@name" />
</xsd:key>
<xsd:keyref name="fromColumn-ref" refer="columnName-key">
<xsd:selector xpath="./ts:Range" />
<xsd:field xpath="@fromColumn" />
</xsd:keyref>
<xsd:keyref name="toColumn-ref" refer="columnName-key">
<xsd:selector xpath="./ts:Range" />
<xsd:field xpath="@toColumn" />
</xsd:keyref>
</xsd:element>
<xsd:element name="Column">
<xsd:complexType>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
<xsd:element name="Range">
<xsd:complexType>
<xsd:attribute name="name" type="xsd:string" use="required" />
<xsd:attribute name="fromColumn" use="optional" type="xsd:string" />
<xsd:attribute name="toColumn" use="optional" type="xsd:string" />
</xsd:complexType>
</xsd:element>
</xsd:schema>
Can I use the selector/field to somehow exclude empty attributes?
I'm trying to create a schema for existing files and would prefer not to have to change them to remove empty attributes.
No, the keyref feature doesn't allow you to treat attributes whose value is a zero-length string differently from other attributes.
XSD tends to be a bit paternalistic in that it only allows you to describe designs that the XSD designers considered to be good practice, and I imagine that the designers of XSD would be telling you that you should omit the attribute here rather than having it present with an empty value.