Estoy intentando crear un escenario de validación en el que quiero elegir al menos un elemento no repetitivo de una lista.

En algún lugar de la línea de:

<xs:choice minOccurs="1" maxOccurs="7">
    <xs:element name="Sunday"/>
    <xs:element name="Monday"/>
    <xs:element name="Tuesday"/>
    <xs:element name="Wednesday"/>
    <xs:element name="Thursday"/>
    <xs:element name="Friday"/>
    <xs:element name="Saturday"/>
</xs:choice>

Sin embargo, la solución anterior permite que aparezcan elementos duplicados en una lista, lo cual no quiero.

Ejemplo de un XML válido :

<Monday/>
<Tuesday/>
<Friday/>

Ejemplo de un XML no válido :

<Monday/>
<Monday/>

¿Se puede lograr esto con un XSD sin tener que codificar todas las secuencias posibles? ¿Si es así, cómo?

6
Daniel André 28 ene. 2016 a las 17:10

2 respuestas

La mejor respuesta

Solución XSD 1.0

No creo que su restricción pueda expresarse en XSD 1.0 " sin tener que codificar todas las secuencias posibles " (pero consulte La inteligente solución de CM Sperberg-McQueen que reduce considerablemente la combinatoria). Los valores de los elementos podrían ser forzados a ser únicos usando xsd:unique, pero el subconjunto de XPath usado por xsd:unique no incluye name(), que de otra manera podría ayudar a hacer una declaración de unicidad sobre los nombres de los elementos.

Solución XSD 1.1

Su restricción se puede expresar en XSD 1.1 usando xs:assert:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" elementFormDefault="qualified"
  vc:minVersion="1.1">
  <xs:element name="Days">
    <xs:complexType>
      <xs:choice minOccurs="1" maxOccurs="7">
        <xs:element name="Sunday"/>
        <xs:element name="Monday"/>
        <xs:element name="Tuesday"/>
        <xs:element name="Wednesday"/>
        <xs:element name="Thursday"/>
        <xs:element name="Friday"/>
        <xs:element name="Saturday"/>
      </xs:choice>
      <xs:assert test="count(*[name() = following-sibling::*/name()]) = 0"/>
    </xs:complexType>
  </xs:element>  
</xs:schema>
4
Community 23 may. 2017 a las 12:30

No dice si la secuencia de elementos tiene significado o no. Para su aplicación, ¿

<Monday/>
<Thursday/>

Significan lo mismo, o algo diferente, de lo que se entiende por

<Thursday/>
<Monday/>

? Si significa lo mismo, entonces no es necesario permitir ambas formas, y puede obtener lo que quiera con

<xs:complexType>
  <xs:sequence>
    <xs:element name="Sunday" minOccurs="0"/>
    <xs:element name="Monday" minOccurs="0"/>
    <xs:element name="Tuesday" minOccurs="0"/>
    <xs:element name="Wednesday" minOccurs="0"/>
    <xs:element name="Thursday" minOccurs="0"/>
    <xs:element name="Friday" minOccurs="0"/>
    <xs:element name="Saturday" minOccurs="0"/>
  </xs:choice>
</xs:complexType>

[Apéndice]. Ups; pasó por alto el requisito de que se seleccione al menos un elemento. La solución obvia XSD 1.0 es algo torpe, pero requiere al menos uno y permite hasta siete elementos, todos diferentes. Utiliza una selección de siete vías entre secuencias que comienzan con domingo, lunes, ...

<xs:complexType>
  <xs:choice>
    <xs:sequence>
      <xs:element name="Sunday"/>
      <xs:element name="Monday" minOccurs="0"/>
      <xs:element name="Tuesday" minOccurs="0"/>
      <xs:element name="Wednesday" minOccurs="0"/>
      <xs:element name="Thursday" minOccurs="0"/>
      <xs:element name="Friday" minOccurs="0"/>
      <xs:element name="Saturday" minOccurs="0"/>
    <xs:sequence>
    <xs:sequence>
      <xs:element name="Monday"/>
      <xs:element name="Tuesday" minOccurs="0"/>
      <xs:element name="Wednesday" minOccurs="0"/>
      <xs:element name="Thursday" minOccurs="0"/>
      <xs:element name="Friday" minOccurs="0"/>
      <xs:element name="Saturday" minOccurs="0"/>
    <xs:sequence>
    <xs:sequence>
      <xs:element name="Tuesday"/>
      <xs:element name="Wednesday" minOccurs="0"/>
      <xs:element name="Thursday" minOccurs="0"/>
      <xs:element name="Friday" minOccurs="0"/>
      <xs:element name="Saturday" minOccurs="0"/>
    <xs:sequence>
    <xs:sequence>
      <xs:element name="Wednesday" />
      <xs:element name="Thursday" minOccurs="0"/>
      <xs:element name="Friday" minOccurs="0"/>
      <xs:element name="Saturday" minOccurs="0"/>
    <xs:sequence>
    <xs:sequence>
      <xs:element name="Thursday"/>
      <xs:element name="Friday" minOccurs="0"/>
      <xs:element name="Saturday" minOccurs="0"/>
    <xs:sequence>
    <xs:sequence>
      <xs:element name="Friday" />
      <xs:element name="Saturday" minOccurs="0"/>
    <xs:sequence>
    <xs:sequence>
      <xs:element name="Saturday" />
    <xs:sequence>
  </xs:choice>
</xs:complexType>
2
C. M. Sperberg-McQueen 28 ene. 2016 a las 16:54