5

I am writing the XSD for an element that has no content, only attributes, which seems fairly straightforward:

  <xs:complexType name="ViewElement">
    <xs:attribute name="Name" type="xs:string" use="required"/>
  </xs:complexType>
  <xs:element name="VIEW" type="ViewElement" minOccurs="0" maxOccurs="unbounded"/>

If the XML contains

<VIEW Name='V_UP'></VIEW>

or

<VIEW Name='V_UP'/>

it works fine. But if the XML contains

<VIEW Name='V_UP'>
</VIEW>

I get

The element cannot contain white space. Content model is empty.

I want to allow the authors of the XML the flexibility to write the XML this way, but I can't work out how to allow content, but only whitespace content. Any suggestions?

kjhughes
  • 106,133
  • 27
  • 181
  • 240
Dave
  • 3,429
  • 2
  • 26
  • 29

2 Answers2

4

You can use a xsd:whiteSpace facet with value="collapse" and require a length of 0:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="OnlyWhiteSpaceElement">
    <xs:simpleType>
      <xs:restriction base="xs:string">
        <xs:whiteSpace value="collapse"/>
        <xs:length value="0"/>
      </xs:restriction>
    </xs:simpleType>
  </xs:element>
</xs:schema>

Update 1: OP would like to add attributes to OnlyWhiteSpaceElement

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="OnlyWhiteSpaceElement">
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="OnlyWhiteSpaceType">
          <xs:attribute name="Name" type="xs:string" use="required"/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:simpleType name="OnlyWhiteSpaceType">
    <xs:restriction base="xs:string">
      <xs:whiteSpace value="collapse"/>
      <xs:length value="0"/>
    </xs:restriction> 
  </xs:simpleType> 
</xs:schema>

See also: Restrict complexType with attributes in XSD?


Update 2: OP would like to reuse the currently anonymous complex type. Let's defined a named type and refactor the names being used...

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="OnlyWhiteSpaceElement" type="OnlyWhiteSpaceType"/>

  <xs:complexType name="OnlyWhiteSpaceType">
    <xs:simpleContent>
      <xs:extension base="OnlyWhiteSpaceContentType">
        <xs:attribute name="Name" type="xs:string" use="required"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>

  <xs:simpleType name="OnlyWhiteSpaceContentType">
    <xs:restriction base="xs:string">
      <xs:whiteSpace value="collapse"/>
      <xs:length value="0"/>
    </xs:restriction> 
  </xs:simpleType> 
</xs:schema>

Update 3: Be aware of XSD processor implementation differences regarding xs:whiteSpace value="collapse".

kjhughes
  • 106,133
  • 27
  • 181
  • 240
  • I get the idea, but unfortunately in the real-life version of my example ViewElement is quite a complicated type and used in several places, so I need to keep the type=ViewElement attribute in the definition of the VIEW element. However, if I then try to add as you suggest, I get an error: "The type attribute cannot be present with either simpleType or compexType". I can't see an obvious way around this. – Dave Sep 10 '18 at 13:42
  • @Dave: Adding attributes to restricted content introduces a lot of distraction from the essential whitespace content aspect of your question, so I omitted it. Since you need help there too, I've updated the answer with an example to show you how. – kjhughes Sep 10 '18 at 13:56
  • I'm sorry if I'm being dumb here, but my understanding of xsd is a bit limited. You seem to have moved the Name attribute out of the type definition and into the element definition. I need the Name attribute in the type definition, which, in real life, has lots of attributes, and is used to define several elements which all have this type of ViewElement. Does that make sense or am I missing the point completely? – Dave Sep 10 '18 at 15:40
  • No problem. Just use a named rather than anonymous type. I've shown you how in another answer update. – kjhughes Sep 10 '18 at 16:28
  • Argh. I really appreciate your help but I still can't get it to work. The error in my XML has changed, it now reads "The value '' is invalid according to its datatype 'ViewElement' - The actual length is not equal to the specified length." That rather looks like the collapse isn't working. If I remove the whitespace and length specifiers the erro goes away - but then of course I can put any non-whitespace content in, which is what I'm trying to prohibit. (I had to put as stackoverflow itself collapsed the actual spaces I put in :-)) – Dave Sep 11 '18 at 15:49
  • @Dave: I've confirmed that the XSD I've posted operates as you've requested. I suggest that you accept this answer and post a new one that includes a [mcve] that exhibits your new issue. I've already answered your original question and several follow-ups. Thanks. – kjhughes Sep 11 '18 at 16:08
  • Fair enough, I'll do that. Thanks for your time. – Dave Sep 11 '18 at 16:10
  • 1
    For the benefit of posterity, this answer is technically correct (thanks kjhughes), but some XSD parsers apparently do not honour the whitespace facet properly, so there is a better answer (also from kjhughes) [here](https://stackoverflow.com/questions/52280613/in-xsd-i-want-to-specify-that-an-element-can-only-have-whitespace-content). – Dave Sep 12 '18 at 13:01
2

We found nesting two empty xs:sequences to be a cleaner solution:

  <xs:element name="a">
    <xs:complexType>
      <xs:sequence>  
        <xs:sequence />
      </xs:sequence>
      <xs:attribute name="test" type="xs:string" />
    </xs:complexType>
  </xs:element>

(tested with libxml)

unilynx
  • 456
  • 3
  • 10