开发者

Restrict the depth of nested elements in XSD

Is it possible with XML schema to restrict the depth of child elements nested in a parent?

The context here is I collect alarms from a management system and I want to provide a XML document which allows the end user define some rules in order to filter the alarms into folders in the UI. I want to restrict the depth of nested folders to 3 so an end user can't nest hundreds of levels deep - as filtering to so many levels would crash the application eventually.

I could write some code to handle this, but it seems appropriate to define this in the schema if its possible.

For example, this would be fine:

<group name="Folder 1">
        <group name="Folder 2">
            <group name="Folder 3">
                <group name="Folder 4">
                </group>
            </group>
        </group>
    </group>

This would be invalid, as Folder 5 is too deep.

<group name="Folder 1">
        <group name="Folder 2">
            <group name="Folder 3">
                <group name="Folder 4">
                    <group name="Folder 5">
                    </group>
                </group>
            </group>
        </group>
    </group>

My schema looks like this, but its not restricting the depth for the snippet above.

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="hierarchy">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="group" type="GroupType" />
      </xs:sequence>
      <xs:attribute name="name" type="xs:string" />
    </xs:complexType>
  </xs:element>

  <xs:complexType name="GroupType">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="1" name="group" type="GroupType" />
    </xs:sequence>
    <xs:attribute name="name" type="xs:string" use="required" />
    <xs:attribute name="fil开发者_Go百科terOn" type="xs:string" use="optional" />
    <xs:attribute name="operator" type="xs:string" use="optional" />
    <xs:attribute name="value" type="xs:string" use="optional" />
  </xs:complexType>
</xs:schema>

Any pointers much appreciated!


A pretty and simple solution is not available in XML Schema (but is in other languages) but you can actually to it, by nesting the whole thing yourself which I can't recommend.

So, if I were you, I would do one of two things:

  1. Pick an alternative to XML Schema (or an extension) See: http://en.wikipedia.org/wiki/XML_schema#XML_schema_languages (take a look at RELAX and Schematron)
  2. Do the depth checking in your application and reject it if depth > 3 and make the behavior clear in the documentation for your XML Schema and application.

Quote from Wiki about XML Schema version 1.1 (candidate recommendation):

The ability to define assertions against the document content by means of XPath 2.0 expressions (an idea borrowed from Schematron)

<- This will do the depth pretty easy to define.

For comment on how to represent nesting depth in XMLSchema:

Basically you can do something like the following (still recommending doing it in code). You then add attributes, adjusting depth etc. (you may be able to reuse attributes with extension or restrict but I'm not 100% sure). This method can get pretty nasty (exponential) if you allow multiple kinds of sub-elements:

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema elementFormDefault="qualified" 
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://somenamespace.com"
           xmlns="http://somenamespace.com">

  <xs:element name="hierarchy">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="group" type="GroupTypeDepth0" />
      </xs:sequence>
      <xs:attribute name="name" type="xs:string" />
    </xs:complexType>
  </xs:element>

  <xs:complexType name="GroupTypeDepth0">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="1" name="group" type="GroupTypeDepth1" />
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="GroupTypeDepth1">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="1" name="group" type="GroupTypeDepth2" />
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="GroupTypeDepth2"/>
</xs:schema>

Valid:

<hierarchy xmlns="http://somenamespace.com">
  <group>
    <group>
      <group/>
    </group>
  </group>
</hierarchy>

Invalid:

<hierarchy xmlns="http://somenamespace.com">
  <group>
    <group>
      <group>
        <group/>
      </group>
    </group>
  </group>
</hierarchy>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜