2009-10-21 15 views
9

Estoy intentando desarrollar un esquema que valide algunos archivos XML existentes que heredé. Me gustaría que el esquema haga la mayor parte del trabajo de validación posible. El desafío es que los atributos y los elementos dependen de los valores de otros atributos.Creación de un esquema XML con atributos y elementos contingentes a otros atributos

La información real es bastante abstracta, así que he creado algunos ejemplos simples. Digamos que tengo los siguientes archivos XML:

<?xml version="1.0" encoding="UTF-8"?> 
<Creature type="human" nationality="British"> 
    <Address>London</Address> 
</Creature> 

<?xml version="1.0" encoding="UTF-8"?> 
<Creature type="animal" species="Tiger"> 
    <Habitat>Jungle</Habitat> 
</Creature> 

Si "tipo" de la criatura es "humano", voy a tener un atributo de "nacionalidad" y una "dirección" elemento secundario. Si el "tipo" de la criatura es "animal", tendré un atributo "especie" y un elemento secundario "Hábitat". A los fines de este ejemplo, un "humano" con una "especie" o un "Hábitat" sería inválido, al igual que un "animal" con una "nacionalidad" o "Dirección".

Si "Criatura" no era el elemento raíz, probablemente podría tener dos opciones diferentes de "Criatura" debajo del elemento raíz, pero no veo cómo puedo hacer que esto funcione cuando "Criatura" es el elemento raíz .

¿Hay alguna forma de crear un esquema para estos archivos que solo coincida con documentos válidos? Si es así, ¿cómo lo haré?

Respuesta

7

Puede usar el atributo xsi: type para este fin (deberá usar el tipo xsi: del espacio de nombres instancia XMLSchema en lugar de su propio espacio de nombres, de lo contrario no funcionará).

En el esquema, declara un tipo base que se declara como abstracto y crea tipos complejos adicionales para cada subtipo (con los elementos/atributos específicos de ese tipo).

Tenga en cuenta que, si bien esta solución funciona, sería mejor utilizar diferentes nombres de elementos para cada tipo (el xsi: tipo va contra corriente, ya que ahora es el atributo de tipo en combinación con el nombre del elemento define el tipo en lugar de solo el nombre del elemento).

por ejemplo:

<?xml version="1.0"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> 

<xs:element name="Creature" type="CreatureType"> 
</xs:element> 

    <xs:complexType name="CreatureType" abstract="true"> 
    <!-- any common validation goes here --> 
    </xs:complexType> 

    <xs:complexType name="Human"> 
    <xs:complexContent> 
     <xs:extension base="CreatureType"> 
     <xs:sequence maxOccurs="1"> 
      <xs:element name="Address"/> 
     </xs:sequence> 
     <xs:attribute name="nationality" type="xs:string"/> 
     </xs:extension> 
    </xs:complexContent> 
    </xs:complexType> 

    <xs:complexType name="Animal"> 
    <xs:complexContent> 
     <xs:extension base="CreatureType"> 
     <xs:sequence maxOccurs="1"> 
      <xs:element name="Habitat"/> 
     </xs:sequence> 
     <xs:attribute name="species" type="xs:string"/> 
     </xs:extension> 
    </xs:complexContent> 
    </xs:complexType> 

</xs:schema> 

Este esquema validará estos dos:

<?xml version="1.0" encoding="UTF-8"?> 
<Creature xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:type="Human" 
      nationality="British"> 
    <Address>London</Address> 
</Creature> 

<?xml version="1.0" encoding="UTF-8"?> 
<Creature xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:type="Animal" 
      species="Tiger"> 
    <Habitat>Jungle</Habitat> 
</Creature> 

pero no esto:

<?xml version="1.0" encoding="UTF-8"?> 
<Creature xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:type="SomeUnknownThing" 
      something="something"> 
    <Something>Something</Something> 
</Creature> 

o esto:

<?xml version="1.0" encoding="UTF-8"?> 
<Creature xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:type="Human" 
      species="Tiger"> 
    <Habitat>Jungle</Habitat> 
</Creature> 
+1

Gracias por la respuesta muy precisa y excelente ejemplo en su solución. Me acabas de ahorrar horas de búsqueda en Internet –

+1

¡Gran ejemplo! ¿Podría explicar por qué 'xsi: type' funciona mientras' type' no aparece en los archivos XML? – Praetorian

+0

Excelente paradigma! Pero en mi especificación de nivel de juego XML, * I * quiero especificar la especificación, y no XML Schema (prefiero "tipo" y no "xsi: tipo"). Entonces, ¿esto es una debilidad del esquema XML? – Chameleon

Cuestiones relacionadas