Sign In/My Account | View Cart  
advertisement

Article:
 Architectural Design Patterns for XML Documents
Subject: Elements with only sub-elements
Date: 2003-06-05 07:40:07
From: Andres Becerra

I am rather new at working with XSD schemas but have been catching on. This question is for something I haven't been able to find an answer to anywhere. Maybe that means that what I want to do is not possible, but I figured I would post the question anyway.


Is there a way to force an element to be able to have sub-elements, any type of sub-elements, but no text within it?


Here is the source XML I use:


<Group attrib1="..." attrib2="...">
<Title>My Title</Title>
<Content>
<!-- in here, any other element
tags are allowed, but straight
text should not be allowed -->
</Content>
</Group>


I got the basic XSD written for this XML structure and this is what it looks like:


<xs:element name="Content">
<xs:complexType>
<xs:complexContent>
<xs:restriction base="xs:anyType">
<xs:attribute name="ContentHeight" type="xs:string" />
</xs:restriction>
</xs:complexContent>
</xs:complexType>
</xs:element>



Now, using this XSD to validate a test Group.xml file, I get a message "Element cannot contain text or whitespace. Content model is empty." This is fine, I don't want the Content tag to have text or whitespace, but even when I put all the source XML on one line and ensure there is no text or whitespace, I still get that error.


If I try to do something like this:


<Group attrib1="..." attrib2="...">
<Title>My Title</Title>
<Content>
<TableView attrib1="..." attrib2="..." />
</Content>
</Group>


I get an error "Element 'Content' has invalid child element 'TableView'". This is a big problem, as I need the <Content> tag to allow any type of element, *only* elements and not straight text. After playing with the XSD a little bit, I found that allowing mixed content (i.e. see mixed="true" on <xs:complexType> below) would get rid of the "Element cannot contain text or whitespace" message. This is not my ideal approach but I can live with it for now. But with the XSD below I still get the message that "Element 'Content' has invalid child element 'TableView'".


<xs:element name="Content">
<xs:complexType mixed="true">
<xs:complexContent>
<xs:restriction base="xs:anyType">
<xs:attribute name="ContentHeight" type="xs:string" />
</xs:restriction>
</xs:complexContent>
</xs:complexType>
</xs:element>


Any pointers to get around this would be greatly appreciated.


Previous Message Previous Message   Next Message Next Message


Titles Only Titles Only Newest First
  • Elements with only sub-elements
    2003-06-05 08:17:21 Kyle Downey

    Without hacking around with the schemas, it's hard for me to say for sure, but I believe the problem is in how you decided to do inheritance. You're using a restriction with base any, which means rather than allowing anything, you're taking "any" and reducing it to no content, plus the attribute you named. You want an <xs:extension/> element instead. See my follow-on article; it includes an example of inheritance-by-extension. But I think there's an easier way to do this which doesn't require any inheritance:


    <complexType>
    <any maxOccurs="unbounded"/>
    <attribute name="ContentHeight" type="string"/>
    </complexType>


    Note that if your intent was to allow any element but wanted to require the ContentHeight attribute on the children rather than the <Content> element, your example would be the way to go, assuming you use <xs:extension/>.


    As one more note, unless mixed="true", the default content type is "elementOnly." To be explict you could do this:


    <complexType content="elementOnly">
    ...
    </complexType>


    but it should be unnecessary.

    • Elements with only sub-elements
      2003-06-06 07:19:16 Andres Becerra

      I came to a solution based on posts by different people. I wanted to share the solution in case anyone ran into this problem in the future. Below is the XSD I ended up using:



      <xs:element name="Content">
      <xs:complexType>
      <xs:sequence>
      <xs:any minOccurs="0" maxOccurs="0" />
      </xs:sequence>
      <xs:attribute name="ContentHeight" type="xs:string" />
      </xs:complexType>
      </xs:element>



      Another option I had was to tightly validate exactly what valid elements are allowed in <Content> elements, using this XSD schema snippet:


      <xs:element name="Content">
      <xs:complexType>
      <xs:complexContent>
      <xs:restriction base="xs:anyType">
      <xs:all>
      <xs:element ref="label" minOccurs="0" />
      <xs:element ref="TableView" minOccurs="0" />
      </xs:all>
      <xs:attribute name="ContentHeight" type="xs:string" />
      </xs:restriction>
      </xs:complexContent>
      </xs:complexType>
      </xs:element>



      I ended up going with the 1st option simply because it was more flexible over the long run. In the near future, there may be transformers written for new elements that can be placed in the <Content> element, so I didn't want to restrict it too much.... just as long as no plain text was allowed in the <Content> element, only sub-elements.


      Cheers,
      Andres


Sponsored By: