Pregunta

Siempre he entendido XMLSchemas y DTD son equivalentes, pero que este último es más complicado de usar al modelar relaciones complejas (como la herencia).

Recientemente me querían construir un esquema para validar los documentos que tienen una estructura como esta:

<data>
 <array>
   <int></int>
   <int></int>
 </array>
 </array>
   <float></float>
   <float></float>
 </array>
 <int><int>
 <float></float>
</data>

Los elementos dentro de <> de datos pueden aparecer en cualquier orden y cada uno es de cardinalidad 0 .. * Usando XMLSchema, si defino un tipo complejo usando puedo tener los elementos fuera de servicio, pero la cardinalidad máxima es 1. y son los otros candidatos obvios pero son más restrictiva que lo que quiero.

Entonces me di cuenta de que una DTD parece ser capaz de lograr esto, así:

<!ELEMENT data (array | float | int)*>

¿Hay alguna manera de construir un esquema equivalente o tengo que usar DTD aquí?

¿Fue útil?

Solución 2

pensé que me gustaría volver a esto como la respuesta anterior es incorrecta. De hecho, uno puede resolver el problema original utilizando el esquema XML.

El enfoque correcto es definir un elemento del grupo del que es contiene una elección entre las diversas opciones (enteros, flotadores, matrices) y cada uno tiene cardinalidad 0 .. *.

<xs:group name="dataTypesGroup">
    <xs:choice>
        <xs:element name="int" type="intType"/>
        <xs:element name="float" type="floatType"/>
        <xs:element name="array">
            <xs:complexType>
                <xs:choice>
                    <xs:element name="int" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/>
                    <xs:element name="float" type="xs:float" minOccurs="0" maxOccurs="unbounded"/>
                </xs:choice>
                <xs:attribute name="id" use="required"></xs:attribute>
            </xs:complexType>    
        </xs:element>
    </xs:choice>
</xs:group>

A partir de aquí, queda por hacer referencia al grupo en una definición de complexType y establecer la cardinalidad del grupo como 0 .. *

<xs:element name="data" minOccurs="0" maxOccurs="unbounded">
    <xs:complexType>
        <xs:group ref="dataTypesGroup" minOccurs="0" maxOccurs="unbounded"/>
    </xs:complexType>
</xs:element>

et voila. un poco prolijo (especialmente en comparación con la sintaxis de RelaxNG) pero la ventaja es que el esquema XML es mucho mejor soportado. Había creado un analizador basado en RelaxNG para resolver el problema original, pero los validadores disponibles (como JING) son bastante más torpe que el uso de las herramientas basadas en XML Schema que se incluyen con Java et al.

Otros consejos

Sólo es factible por medio de XSD si se mantiene el orden de sus elementos (por lo que puede utilizar un xs: secuencia ). Es decir, un flotador Siempre habrá llegado después de un array (si lo hay), y y un int Siempre habrá llegado después de un flotador (si lo hay), teniendo en cuenta que se puede repetir tantas como desee ocurreces de cada tipo (o Omisión de ellos por completo).

La razón es que XSD xs: todos tipo complejo no soporta ilimitada atributo para cualquiera de sus tipos de contenido (elementos, otros tipos de grupos anidados, etc.). Otro esquema más "relajado" permitirá que lo haga, como DTD, como usted indica, o RelaxNG por ejemplo.

Aquí está una muestra de XSD que se ajuste a su archivo XML:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:complexType name="arrayType">
            <xs:sequence>
                <xs:element name="array" type="arrayType" minOccurs="0" maxOccurs="unbounded"/>
                <xs:element name="int" minOccurs="0" maxOccurs="unbounded"/>
                <xs:element name="float" minOccurs="0" maxOccurs="unbounded"/>
            </xs:sequence>
    </xs:complexType>
    <xs:element name="data" type="arrayType"/>
</xs:schema>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top