0

My goal/question is to understand how to create DTD or Schema for XML where an enumeration of values for an attribute can include null as a valid value.

The W3C spec for XML defines attribute validity constraints, one of which is an Enumeration. This is a hard-coded list of valid values for attributes. Example:

<foo att="aaa" />

The value "aaa" must be in the list of valid attributes for element foo or the attribute may be flagged by DTD or XSD.

That list may be defined in DTD in the !ATTLIST as follows:

att ( aaa | bbb ) #IMPLIED

In XSD it looks like this:

<xs:attribute name="att">
  <xs:simpleType>
    <xs:restriction base="xs:NMTOKEN">
      <xs:enumeration value="aaa" />
      <xs:enumeration value="bbb" />
    </xs:restriction>
  </xs:simpleType>
</xs:attribute>

Now, what if an empty value is acceptable? I'm not talking about a #IMPLIED = optional attribute. I'm talking about an attribute where an empty value is just as valid as "aaa" or "bbb". The following DTD and XSD are not valid:

<!ATTLIST att ( | aaa | bbb ) #IMPLIED>

<xs:attribute default="" name="att">
  <xs:simpleType>
    <xs:restriction base="xs:NMTOKEN">
      <xs:enumeration value="" />
      <xs:enumeration value="aaa" />
      <xs:enumeration value="bbb" />
    </xs:restriction>
  </xs:simpleType>
</xs:attribute>

In those examples, the att attribute is optional (#IMPLIED) but if it is present it should also allow an empty value: att="". The XSD takes it a step further to state that if the value is not present that its value will be assigned null.

The validation for such attributes must conform to this pattern (from section 3.3.1, example [59]) :

Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'

That regex defines the DTD sequence above "( aaa | bbb )". After zero or one space "S?" we can have a Nmtoken, optionally followed by another space and pipe for more Nmtokens. The Nmtoken is defined in section 2.3 as beginning with a NameStartChar. There is no allowance for null. The NameStartChar cannot be a quote or empty string.

But in common code we can define an element of an enumeration as an empty string, and we can define nullable types including Enumerations. More specifically there is code where we pass in a string to a method which is then validated against an enumeration.

The problem/application I'm trying to solve is about how to define valid XML syntax in DTD and/or XSD where the code processing the XML can accept an empty string. Without this, the XML doesn't validate att="" even though it's valid. Do we care? Well, for the code I'm working with now, I do.

Let's not get into the validity of empty strings in an enum, using enum.None, using method(Enum val) rather than method(String val), etc. The fact is that this code is out in the wild. It exists in common FOSS, it works, and we're not going to re-write it. The problem is creating XML faithfully defines the code.

There is XSD syntax to define alternative values for an attribute. I'd accept a pattern for that that works for this scenario. In my immediate project, I'm generating DTD (Ant task AntStructure) and converting that to XSD. The DTD is invalid, so the XSD is too. I'd like to do this with the DTD but it's not critical.

1 Answer 1

0

In XSD, just define the type as a restriction of xs:string rather than xs:NMTOKEN. The type xs:NMTOKEN doesn't allow a zero-length string, so if you want a zero-length string then it can't be an xs:NMTOKEN.

(Not sure what the equivalent in DTDs is, it's been a very long time...)

1
  • That's a good answer for XSD for now. Let's see what other suggestions come up. Thanks.
    – TonyG
    Jan 14, 2020 at 0:01

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .