Creating a Flexible XML Schema

I need to create a schema for an XML file, which is quite flexible. It must meet the following requirements:

  • Confirm some of the elements we need to be present and find out the exact structure.
  • Confirm some items that are optional and we know the exact structure
  • Allow any other items.
  • Allow them in any order.

Quick example:

XML

<person> <age></age> <lastname></lastname> <height></height> </person> 

My XSD attempt:

 <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="person"> <xs:complexType> <xs:sequence> <xs:element name="firstname" minOccurs="0" type="xs:string"/> <xs:element name="lastname" type="xs:string"/> <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded" /> </xs:sequence> </xs:complexType> </xs:element> </xs:schema> 

Now my XSD satisfies requirements 1 and 3. However, this is not a valid scheme if both first and last names were optional, therefore it does not meet requirement 2, and the order is fixed, which does not meet requirements 4.

Now all I have to do is check my XML. I am open to suggestions on any of the ways to do this, either programmatically in .NET 3.5, another type of circuit, etc.

Can anyone think of a solution that satisfies all 4 requirements?

+4
source share
2 answers

Today I thought a lot about this problem. I considered how strong this xs:all rule is for XML databases to store documents that have not structured "CMS" as data, as well as validating the data.

Then it occurred to me that XHTML allows you to very flexibly place nested elements in any order in which you need to mark the page.

So here is an excerpt from the XHTML 1.1 schema:

  <xs:group name="InlForm.class"> <xs:choice> <xs:element ref="input"/> <xs:element ref="select"/> <xs:element ref="textarea"/> <xs:element ref="label"/> <xs:element ref="button"/> </xs:choice> </xs:group> <xs:group name="Inline.extra"> <xs:choice/> </xs:group> <xs:group name="Ruby.class"> <xs:sequence> <xs:element ref="ruby"/> </xs:sequence> </xs:group> <!-- Inline.class includes all inline elements, used as a component in mixes --> <xs:group name="Inline.class"> <xs:choice> <xs:group ref="InlStruct.class"/> <xs:group ref="InlPhras.class"/> <xs:group ref="InlPres.class"/> <xs:group ref="I18n.class"/> <xs:group ref="Anchor.class"/> <xs:group ref="InlSpecial.class"/> <xs:group ref="InlForm.class"/> <xs:group ref="Ruby.class"/> <xs:group ref="Inline.extra"/> </xs:choice> </xs:group> <xs:group name="Heading.class"> <xs:choice> <xs:element ref="h1"/> <xs:element ref="h2"/> <xs:element ref="h3"/> <xs:element ref="h4"/> <xs:element ref="h5"/> <xs:element ref="h6"/> </xs:choice> </xs:group> 

They essentially nest in the choice of groups, recursively. I believe that the person who wrote this lives the rest of his days in a safe facility, receiving compulsory medications several times a day.

Hope this helps. I think this illustrates how super-flexi schemes actually execute in XSD 1.0.

Change - it works! You can create a β€œcore” group of all other groups and use this example ListItem element ListItem to allow continuous nested elements in any order. Make sure ListItem also included in the group, so recursion works.

  <xs:element name="ListItem"> <xs:complexType> <xs:sequence> <xs:group ref="content:any.mix" minOccurs="1" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> 

So my group any.mix looks like this:

  <xs:group name="any.mix"> <xs:choice> <xs:group ref="content:item.class" /> <xs:group ref="content:media.class" /> <xs:group ref="content:data.class" /> <xs:group ref="content:list.class" /> </xs:choice> </xs:group> 

And each of these class groups contains even more group options, etc. etc., until they ultimately hit the elements, the actual sheet-level tags, if you want.

Groups themselves should not have circular references; the "trick" is in unlimited occurrences of the any.mix group, i.e. in the form of a tree of options with an unlimited choice of root.

Luke

+1
source

Your claim number 3 cannot be addressed if the name elements are optional, because your scheme will violate the unique rule of particle attribution (basically, the processor will not know whether to check the first name on behalf of or against any).

You are not limited to a single verification scheme. If you're fine using two schemas in different namespaces, you can do this:

One scheme - allow all:

 <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="document"> <xs:complexType> <xs:sequence> <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded" /> </xs:sequence> </xs:complexType> </xs:element> </xs:schema> 

Scheme two - add a specific check for some elements:

 <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://other" xmlns="http://other"> <xs:element name="firstname" type="xs:string"/> <xs:element name="lastname" type="xs:string"/> </xs:schema> 

Then, make sure your xsi: include instance document references both schemas.

+6
source

Source: https://habr.com/ru/post/1306228/


All Articles