No puede hacer la validación que busca, con solo XML Schema.
Según la "XML Schema Part 1: Structures" specification ...
Cuando dos o más partículas contenidas directa o indirectamente en los {partículas} de un grupo de modelo han nombrado idénticamente declaraciones de elementos como su {término}, las definiciones de tipos de esas declaraciones debe ser el mismo.
No es que no se puede construir un esquema que valide un documento correcto. Lo que significa es que no puede crear un esquema que no se pueda validar en algunos documentos incorrectos. Y cuando digo "incorrecto", me refiero a los documentos que infringen las restricciones que usted indicó en inglés.
Por ejemplo, suponga que tiene un documento que incluye tres elementos de la calle, así:
<Address Field="Street" Value="123 Main"/>
<Address Field="Street" Value="456 Main"/>
<Address Field="Street" Value="789 Main"/>
<Address Field="SomeOtherCrazyValue" Value="Foo"/>
De acuerdo con el esquema, ese documento es una dirección válida. Es posible agregar una restricción xs:unique a su esquema para que rechace tales documentos rotos. Pero incluso con un xs: único, la validación contra dicho esquema declararía que algunos otros documentos incorrectos son válidos, por ejemplo, un documento con tres elementos <Address>
, cada uno de los cuales tiene un único atributo Field
, pero ninguno de los cuales tiene Field="Zip"
.
De hecho, no es posible producir un esquema W3C XML que codifique formalmente sus restricciones establecidas. El elemento <xs:all>
casi te lleva por aquí, pero se aplica solo a los elementos, no a los atributos. Y no se puede usar con una extensión, por lo que no se puede decir, en W3C XML Schema, "todos estos elementos en cualquier orden, más cualquier otro".
Para llevar a cabo la validación que busca, las opciones son:
- se basan en algo que no sea XML Schema,
- realizar la validación en varios pasos, utilizando el esquema XML para el primer paso y algo más para el segundo paso.
Para la primera opción, creo que podría utilizar Relax NG para hacerlo. La desventaja de esto es que no es un estándar y, por lo que yo sé, no es ampliamente compatible ni está creciendo. Sería como aprender gaélico para expresar un pensamiento. No hay nada de malo en gaélico, pero es una especie de callejón sin salida lingüística, y I think RelaxNG is, too.
Para la segunda opción, un enfoque sería para validar contra de su esquema como el primer paso, y luego, como segunda etapa:
A. aplicar una transformación XSL que convertiría <Address>
elementos en elementos nombrados por el valor de su atributo de campo. La salida de esa transformación se vería así:
<root>
<Street Value="101 Bellavista Drive"/>
<State Value="Confusion"/>
<Zip Value="10101"/>
</root>
B. validar la salida de ese transformada con un esquema diferente, que es como la siguiente:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="root">
<xs:complexType>
<xs:all>
<xs:element maxOccurs="1" minOccurs="1" ref="Street" />
<xs:element maxOccurs="1" minOccurs="1" ref="State" />
<xs:element maxOccurs="1" minOccurs="1" ref="Zip" />
</xs:all>
</xs:complexType>
</xs:element>
<xs:element name="Street">
<xs:complexType>
<xs:attribute name="Value" use="required" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:element name="State">
<xs:complexType>
<xs:attribute name="Value" use="required" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:element name="Zip">
<xs:complexType>
<xs:attribute name="Value" use="required" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:schema>
lo que se necesita para extender ese esquema para manejar otros elementos como <SomeOtherCrazyValue>
en la salida de la transformación. O bien, podría estructurar la transformación xsl para que simplemente no emita elementos que no sean uno de {State, Street, Zip}.
Para que quede claro, entiendo que no puede cambiar el XML que recibe. Este enfoque no requeriría eso. Solo usa un enfoque de validación en dos pasos funky. Una vez que se complete el segundo paso de validación, puede descartar el resultado de la transformación.
EDITAR - En realidad, Sean, pensando en esto de nuevo, es posible que utilices el paso B. Supongamos transformar su XSL Elimina del documento sólo <Address>
elementos que no tienen Estado, Calle o Código Postal para el valor de atributo de campo. En otras palabras, no habría <Address Field="SomeOtherCrazyValue"...>
. El resultado de esa transformación podría validarse con su esquema, utilizando maxOccurs = "3", minOccurs = "3" y xs: unique.
No creo que su sugerencia trabajaría de todos modos, incluso si usted no tiene la posibilidad de tener los atributos SomeOtherCrazyValue. El motivo es que su esquema propuesto se declararía como válido, un documento XML que tenía 3 elementos '
', cada uno con un atributo Street. (Sin código postal, sin estado). Su esquema no se ocupará de eso. – CheesoHmm, eso es cierto. En mi dominio, otros factores evitarían que esto sucediera. Pero en el caso general definitivamente podría. Agregaré una nota en la pregunta original sobre esa parte. Por supuesto, mi pregunta real aún está abierta. Gracias Cheeso! – scrotty