2010-05-19 16 views
6

Trabajo con algunos archivos XML de forma regular y quiero tener una mejor validación que una DTD. Entonces comencé a leer sobre esquemas para ver si me ayudaría. Hasta ahora he podido crear algo que funciona casi como lo que necesito, excepto por una sola pieza. Quiero poder restringir el atributo de un elemento a los valores de un atributo diferente de elementos hermanos o antepasados ​​que son del mismo tipo de elemento. ¿Esto es posible incluso con restricciones de key/keyref de XML Schema?Cómo crear un esquema xml con clave/keyrefs para elementos anidados del mismo tipo

Tengo un documento que se ve algo como esto:

<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> 

En este documento, los nodos se puede "extender" otros nodos que son:

  • hermanos
  • los hermanos de los padres

Sin embargo, los nodos no deben "extenderse":

  • padres
  • nodos hijos de los hermanos de los padres

Esto significa que MyHouse puede "extender" Tabla, que no tiene sentido, pero estoy de acuerdo con eso.

También es importante que ambos nodos de la casa puedan tener sus propios nodos llamados Dining Room.

Y mi esquema actual es similar a esto:

<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> 

Este esquema hace parte de lo que estoy buscando. Establece las claves para que sean los nombres del primer nivel de nodos en nodeContainer, y esas claves se pueden usar para "extender" cualquier nodo en cualquier nivel en nodeContainer o debajo de él. Y eso funciona siempre y cuando no quiera "extender" a los hermanos a niveles más bajos. El documento ejemplo anterior no valida, porque de esta línea:

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

En el esquema que he creado RoomWithDoor no es una clave válida para asignar a "se extiende" ya que no es parte del primer nivel de nodos en nodeContainer. Pero, ¿hay alguna forma de escribir las claves/claves para que sean claves válidas? ¿La ubicación de las teclas/definiciones keyref hace la diferencia? ¿Son mis xpaths demasiado específicos (cómo pueden ser menos específicos)?

Respuesta

0

¿Qué pasaría si cambia el selector XPath para UniqueNodes a

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

En otras palabras - cualquier elemento nodo bajo el nodeContainer. ¿No permitiría eso lo que quiere lograr?

Cuestiones relacionadas