significado partir crear xml xsd schema xml-attribute

partir - ¿Cómo hacer atributos mutuamente exclusivos en el esquema XML?



crear dtd a partir de xml (6)

Ya que RelaxNG fue mencionado en la respuesta de Alnitak, aquí hay una solución con RelaxNG (un lenguaje que es, en la mayoría de los casos, mejor que el esquema W3C). Observe el OR (|) en la definición de elem:

start = document document = element document {elem+} elem = element elem {ref | value} ref = attribute ref {text} value = attribute value {xsd:integer}

Si tengo este archivo XML:

<document> <elem value="1" /> <elem ref="something else" /> </document>

Es aceptado por rnv y xmlint :

% rnv attributes-exclusive.rnc attributes-exclusive.xml attributes-exclusive.xml % xmllint --noout --relaxng attributes-exclusive.rng attributes-exclusive.xml attributes-exclusive.xml validates

Si agrego en el archivo XML:

<elem value="1" ref="something else" />

Obtengo los errores de validación, como quiero (tenga en cuenta que los mensajes de error son subóptimos):

% rnv attributes-exclusive.rnc attributes-exclusive.xml attributes-exclusive.xml attributes-exclusive.xml:4:0: error: attribute ^ref not allowed required: after % xmllint --noout --relaxng attributes-exclusive.rng attributes-exclusive.xml attributes-exclusive.xml:4: element elem: Relax-NG validity error : Invalid attribute value for element elem attributes-exclusive.xml fails to validate

Estoy tratando de hacer que dos atributos XML sean mutuamente excluyentes. ¿Cómo se puede crear un esquema XSD para capturar este tipo de escenario?

Me gustaría tener uno de estos

<elem value="1" /> <elem ref="something else" />

pero no

<elem value="1" ref="something else" />


XSD tiene tipos abstractos para esto: http://www.tek-tips.com/viewthread.cfm?qid=1364846 (ver la publicación de tsuji)

Básicamente, le da al elemento en cuestión un tipo abstracto y complejo y define sus atributos comunes allí, que son exactamente los mismos para todos los casos de uso diferentes (no necesarios para su ejemplo).

Luego, crea 2 (o más) tipos complejos adicionales que extienden el tipo abstracto que acabo de mencionar. Dentro de estos nuevos tipos, usted define los diferentes conjuntos de atributos entre cada caso de uso. Eso es todo por la parte XSD.

Finalmente, debe agregar un atributo de type XSI al elemento resultante en el documento de instancia del esquema. Entonces, para ser válido, el elemento ahora debe tener un conjunto de atributos o el otro.

No es sencillo, sino flexible, y como todos sabemos: cuanto más flexible, más difícil se vuelve algo.


Para los lectores que vienen a esto más adelante, tenga en cuenta que el problema se puede resolver en XSD 1.1 utilizando "asignación de tipo condicional" o aserciones.


En realidad, es posible definir esto en XSD 1.0 utilizando restricciones de identidad a través de xs: unique o xs: key. El que elijas depende de cómo se tratarán los elementos sin ninguno de los dos atributos: Son válidos con xs: únicos pero no válidos con xs: clave. El ejemplo de código a continuación contiene ambas variantes; asegúrese de eliminar uno de ellos, de lo contrario, la clave "más estricta" xs: tiene prioridad sobre xs: única, es decir, se requiere uno de los dos atributos.

<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xs:element name="container"> <xs:complexType> <xs:sequence> <xs:element name="elem" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="value" use="optional"/> <xs:attribute name="ref" use="optional"/> </xs:complexType> <!-- Note: Use either xs:unique or xs:key --> <xs:unique name="attrsExclusiveOptional"> <xs:annotation> <xs:documentation>Ensure that @value and @ref cannot occur simultaneously. Both may be omitted.</xs:documentation> </xs:annotation> <xs:selector xpath="."/> <xs:field xpath="@value | @ref"/> </xs:unique> <xs:key name="attrsExclusiveRequired"> <xs:annotation> <xs:documentation>Ensure that @value and @ref cannot occur simultaneously. One of them is required.</xs:documentation> </xs:annotation> <xs:selector xpath="."/> <xs:field xpath="@value | @ref"/> </xs:key> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>

Esto valida el siguiente archivo XML:

<?xml version="1.0" encoding="UTF-8"?> <container xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schema.xsd"> <!-- Shall pass: --> <elem value="1" /> <elem ref="something else" /> <!-- Passes for xs:unique, fails for xs:key: --> <elem /> <!-- Shall fail: --> <elem value="1" ref="something else" /> </container>


Desafortunadamente AFAIK no puede hacer eso con XML Schema, yo mismo he tenido el mismo problema.

Lo he visto sugiriendo que si necesitas los dos:

<elem type="xxx"> <elem ref="yyy">

entonces <elem> sí debería dividirse en dos tipos, ya que claramente tienen diferentes atributos ...


No se puede hacer con atributos, pero se puede con elementos secundarios ...

<element name="elem"> <complexType> <choice> <element name="value"/> <element name="ref"/> </choice> </complexType> </element>

De esta manera puedes tener ...

<elem> <value>1</value> </elem>

o...

<elem> <rel>something else</rel> </elem>