How to create an xml schema with the key / keyrefs for nested elements of the same type

I work with some XML files on a regular basis and want to have the best validation that DTD can provide. So I started reading about schemes to find out if that would help me. So far, I have been able to create something that works almost the way I need, with the exception of one part. I want to be able to limit the attribute of an element to the values ​​of another attribute of sibling or ancestor elements that have the same element type. Is this possible with XML schema / keyref constraints?

I have a document that looks something like this:

<nodeContainer> <node name="Table"> </node> <node name="MyHouse"> <node name="RoomWithDoor"> </node> <node name="DiningRoom" extends="RoomWithDoor"> <node name="DiningTable" extends="Table"> </node> </node> </node> <node name="MySummerHouse"> <node name="DiningRoom"> <node name="DiningTable" extends="Table"> </node> </node> </node> </nodeContainer> 

In this document, nodes can β€œexpand” other nodes that:

  • brothers and sisters
  • siblings of parents

however, the nodes should not "expand":

  • Parents
  • child nodes of parent siblings

This means that MyHouse can "expand" the table, which makes no sense, but I'm fine with that.

It is also important that both nodes of the node can have their own nodes with the name DiningRoom.

And my current schema looks like this:

 <xs:complexType name="node"> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element ref="node"/> <!-- node can have other nodes inside it --> <xs:element ref="leaf"/> </xs:choice> <xs:attribute name="name" type="xs:anySimpleType" use="required"/> <xs:attribute name="extends" type="xs:anySimpleType"/> </xs:complexType> <!-- document root --> <xs:element name="root"> <xs:complexType> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="nodeContainer"> <xs:complexType> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element ref="node"/> </xs:choice> </xs:complexType> </xs:element> <xs:element ref="otherType"/> </xs:choice> </xs:complexType> <!-- create constrictions --> <xs:unique name="UniqueNodes"> <xs:selector xpath="nodeContainer/node"/> <xs:field xpath="@name"/> </xs:unique> <xs:keyref refer="UniqueNodes" name="ValidNodeExtends"> <xs:selector xpath=".//node"></xs:selector> <xs:field xpath="@extends"></xs:field> </xs:keyref> </xs:element> 

This diagram does part of what I am looking for. It sets the keys as first-level names of nodes in a nodeContainer, and these keys can be used to β€œexpand” any node at any level in or below the node. And this works as long as I don't want to β€œextend” the siblings to lower levels. The above sample document is not checked due to this line:

 <node name="DiningRoom" extends="RoomWithDoor"> 

In the diagram I created, RoomWithDoor is not a valid key for assigning "extends", since it is not part of the first level of nodes in nodeContainer. But is there anyway to write the keys / keyrefs to make them valid? Is there a definition of keys / keyref? Are my xpaths too specific (how can they be less specific)?

+6
xml schema xsd xsd-validation keyref
source share
1 answer

What happens if you change the XPath selector to UniqueNodes to

 <xs:selector xpath="nodeContainer//node"/> 

In other words, any node element under the Container node. Is it not possible to achieve what you want to achieve?

0
source share

All Articles