xml - tutorial - xsd atributos
XSD: ¿cómo permitir elementos en cualquier orden varias veces? (6)
Pero por lo que entiendo xs: la opción todavía solo permite la selección de un solo elemento. Por lo tanto, establecer MaxOccurs en este tipo de límites solo debería significar que "cualquiera" de los elementos secundarios puede aparecer varias veces. Es esto exacto?
No. La elección ocurre individualmente para cada "repetición" de xs:choice
que ocurre debido a maxOccurs="unbounded"
. Por lo tanto, el código que ha publicado es correcto, y realmente hará lo que quiera tal como está escrito.
Intento crear un XSD y tratar de escribir la definición con el siguiente requisito:
- Permitir que el elemento secundario especificado aparezca varias veces (de 0 a ilimitado)
- Permitir que los elementos secundarios estén en cualquier orden
Miré a mi alrededor y encontré varias soluciones como this :
<xs:element name="foo">
<xsl:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="child1" type="xs:int"/>
<xs:element name="child2" type="xs:string"/>
</xs:choice>
</xs:complexType>
</xs:element>
Pero por lo que entiendo xs: la opción todavía solo permite la selección de un solo elemento. Por lo tanto, establecer MaxOccurs en este tipo de límites solo debería significar que "cualquiera" de los elementos secundarios puede aparecer varias veces. Es esto exacto?
Si la solución anterior es incorrecta, ¿cómo puedo lograr lo que dije antes en mi requerimiento?
EDITAR : ¿Qué pasa si el requisito es el siguiente?
- El elemento child1 child2 puede aparecer cualquier cantidad de veces (de 0 a ilimitado)
- Elementos para estar en cualquier orden
- Los elementos child3 y child4 deberían aparecer exactamente una vez.
Por ejemplo, este xml es válido:
<foo>
<child1> value </child1>
<child1> value </child1>
<child3> value </child3>
<child2> value </child2>
<child4> value </child4>
<child1> value </child1>
</foo>
pero esto no es (niño perdido3)
<foo>
<child1> value </child1>
<child1> value </child1>
<child2> value </child2>
<child4> value </child4>
<child1> value </child1>
</foo>
Debería encontrar que el siguiente esquema le permite lo que ha propuesto.
<xs:element name="foo">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:choice>
<xs:element maxOccurs="unbounded" name="child1" type="xs:unsignedByte" />
<xs:element maxOccurs="unbounded" name="child2" type="xs:string" />
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
Esto le permitirá crear un archivo como:
<?xml version="1.0" encoding="utf-8" ?>
<foo>
<child1>2</child1>
<child1>3</child1>
<child2>test</child2>
<child2>another-test</child2>
</foo>
Lo cual parece coincidir con tu pregunta.
En el esquema que tiene en su pregunta, child1
o child1
pueden aparecer en cualquier orden, cualquier cantidad de veces. Así que esto suena como lo que estás buscando.
Editar: si quisiera que solo una de ellas apareciera un número ilimitado de veces, la ilimitada tendría que ir en los elementos en su lugar:
Editar: tipo fijo en XML.
Editar: O mayúscula en maxOccurs
<xs:element name="foo">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="child1" type="xs:int" maxOccurs="unbounded"/>
<xs:element name="child2" type="xs:string" maxOccurs="unbounded"/>
</xs:choice>
</xs:complexType>
</xs:element>
Esto es lo que finalmente funcionó para mí:
<xsd:element name="bar">
<xsd:complexType>
<xsd:sequence>
<!-- Permit any of these tags in any order in any number -->
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="child1" type="xsd:string" />
<xsd:element name="child2" type="xsd:string" />
<xsd:element name="child3" type="xsd:string" />
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
La formulación alternativa de la pregunta agregada en una edición posterior parece que aún no ha sido respondida: cómo especificar que entre los elementos child4
de un elemento, debe haber un nombre llamado child3
, uno llamado child4
y cualquier número llamado child1
o child1
, sin restricción en el orden en que aparecen los niños.
Este es un lenguaje regular definible directamente, y el modelo de contenido que necesita es isomorfo a una expresión regular que define el conjunto de cadenas en el que los dígitos ''3'' y ''4'' ocurren exactamente una vez, y los dígitos ''1'' y ''2 ''ocurren muchas veces. Si no es obvio cómo escribir esto, puede ser útil pensar en qué tipo de máquina de estados finitos construirá para reconocer dicho lenguaje. Tendría al menos cuatro estados distintos:
- un estado inicial en el que no se ha visto ni ''3'' ni ''4''
- un estado intermedio en el que se ha visto ''3'' pero no ''4''
- un estado intermedio en el que se ha visto ''4'' pero no ''3''
- un estado final en el cual ambos ''3'' y ''4'' han sido vistos
No importa en qué estado se encuentre el autómata, se pueden leer ''1'' y ''2''; ellos no cambian el estado de la máquina. En el estado inicial, también se aceptarán ''3'' o ''4''; en los estados intermedios, solo se acepta "4" o "3"; en el estado final, ni ''3'' ni ''4'' son aceptados. La estructura de la expresión regular es más fácil de entender si primero definimos una expresión regular para el subconjunto de nuestro idioma en el que solo aparecen ''3'' y ''4'':
(34)|(43)
Para permitir que ''1'' o ''2'' ocurran cualquier cantidad de veces en una ubicación determinada, podemos insertar (1|2)*
(o [12]*
si nuestro lenguaje regex acepta esa notación). Al insertar esta expresión en todas las ubicaciones disponibles, obtenemos
(1|2)*((3(1|2)*4)|(4(1|2)*3))(1|2)*
Traducir esto a un modelo de contenido es sencillo. La estructura básica es equivalente a la expresión regular (34)|(43)
:
<xsd:complexType name="paul0">
<xsd:choice>
<xsd:sequence>
<xsd:element ref="child3"/>
<xsd:element ref="child4"/>
</xsd:sequence>
<xsd:sequence>
<xsd:element ref="child4"/>
<xsd:element ref="child3"/>
</xsd:sequence>
</xsd:choice>
</xsd:complexType>
Insertar una opción cero o más de child1
y child1
es sencillo:
<xsd:complexType name="paul1">
<xsd:sequence>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="child1"/>
<xsd:element ref="child2"/>
</xsd:choice>
<xsd:choice>
<xsd:sequence>
<xsd:element ref="child3"/>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="child1"/>
<xsd:element ref="child2"/>
</xsd:choice>
<xsd:element ref="child4"/>
</xsd:sequence>
<xsd:sequence>
<xsd:element ref="child4"/>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="child1"/>
<xsd:element ref="child2"/>
</xsd:choice>
<xsd:element ref="child3"/>
</xsd:sequence>
</xsd:choice>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="child1"/>
<xsd:element ref="child2"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
Si queremos minimizar un poco el volumen, podemos definir un grupo nombrado para las opciones repetitivas de child1
y child1
:
<xsd:group name="onetwo">
<xsd:choice>
<xsd:element ref="child1"/>
<xsd:element ref="child2"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="paul2">
<xsd:sequence>
<xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
<xsd:choice>
<xsd:sequence>
<xsd:element ref="child3"/>
<xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="child4"/>
</xsd:sequence>
<xsd:sequence>
<xsd:element ref="child4"/>
<xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="child3"/>
</xsd:sequence>
</xsd:choice>
<xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
En XSD 1.1, algunas de las restricciones en all
grupos se han eliminado, por lo que es posible definir este modelo de contenido de manera más concisa:
<xsd:complexType name="paul3">
<xsd:all>
<xsd:element ref="child1" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="child2" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="child3"/>
<xsd:element ref="child4"/>
</xsd:all>
</xsd:complexType>
Pero como se puede ver en los ejemplos dados anteriormente, estos cambios en all
grupos no cambian el poder expresivo del lenguaje; solo hacen más sucinta la definición de ciertos tipos de idiomas.
Si ninguno de los anteriores está funcionando, es probable que esté trabajando en la tradia EDI donde necesita validar su resultado contra un esquema HIPPA o cualquier otro xsd complejo para ese asunto. El requisito es que, digamos que hay 8 segmentos REF y cualquiera de ellos debe aparecer en cualquier orden y tampoco todos son obligatorios, significa decir que puede tenerlos en el siguiente orden: 1ª REF, 3ª REF, 2ª REF, 9ª REF. En la situación predeterminada, la recepción de EDI fallará, ya que el tipo complejo predeterminado es
<xs:sequence>
<xs:element.../>
</xs:sequence>
La situación es incluso compleja cuando llamas a tu elemento por refrencia y luego ese elemento en su lugar original es bastante complejo. por ejemplo:
<xs:element>
<xs:complexType>
<xs:sequence>
<element name="REF1" ref= "REF1_Mycustomelment" minOccurs="0" maxOccurs="1">
<element name="REF2" ref= "REF2_Mycustomelment" minOccurs="0" maxOccurs="1">
<element name="REF3" ref= "REF3_Mycustomelment" minOccurs="0" maxOccurs="1">
</xs:sequence>
</xs:complexType>
</xs:element>
Solución:
¡Aquí simplemente reemplazar "secuencia" por "todo" o usar "elección" con combinaciones mínimas / máximas no funcionará!
Primero, reemplace "xs:sequence" with "<xs:all>"
Ahora, necesita hacer algunos cambios desde donde está refiriendo el elemento, vaya a:
<xs:annotation>
<xs:appinfo>
<b:recordinfo structure="delimited" field.........Biztalk/2003">
*** Ahora, en el segmento anterior, agregue el punto de activación al final como este trigger_field = "REF01 _... nombre completo ..." trigger_value = "38" Haga lo mismo para otros segmentos REF donde el valor de activación será diferente, como por ejemplo "18 "," XX "," YY ", etc., de modo que su información de registro ahora se ve así: b:recordinfo structure="delimited" field.........Biztalk/2003" trigger_field="REF01_...complete name.." trigger_value="38">
Esto hará que cada elemento sea único, razón por la cual todos los segements de REF (ejemplo anterior) tienen la misma estructura como REF01, REF02, REF03. Y durante la validación, la validación de la estructura está bien, pero no permite que los valores se repitan porque trata de buscar los valores restantes en la primera REF. Agregar disparadores los hará únicos y pasarán en cualquier orden y casos situacionales (como usar 5 de 9 y no todos 9/9).
Espero que te ayude, porque pasé casi 20 horas en esto.
Buena suerte