2010-06-11 12 views
13

Quiero tener la lista de elementos requeridos en cualquier orden definido en dtd, pero no tengo idea de cómo podría hacer esto.DTD requirió elementos que ordenan

Por ejemplo, he siguiente definición:

<!ELEMENT parent (child1, child2, child3)> 

Esta declaración DTD validar correctamente siguiente fragmento de XML:

<parent> 
    <child1></child1> 
    <child2></child2> 
    <child3></child3> 
</parent> 

Pero en caso siguiente XML no pasará la validación:

<parent> 
    <child2></child2> 
    <child1></child1> 
    <child3></child3> 
</parent> 

Una de la posible solución es declarar

<!ELEMENT parent (child1 | child2 | child3)> 

Pero en este caso puede que falte uno de los hijos, aunque la validación será exitosa.

Necesito la declaración correcta del elemento dtd para el caso cuando la lista de elementos requeridos puede estar presente en cualquier orden.

+0

Casi me envió esta pregunta hace unos minutos. Totalmente cojo que no puedes volver a ordenar estos. – livingtech

Respuesta

11

ChrisF es incorrecto decir que no puedes hacer esto (pero felicitaciones por comprobar las especificaciones); DevNull [ahora conocido como Daniel Haley] tiene razón al decir que puedes.

Sin embargo, hay una complicación: el modelo de contenido dado por DevNull para padre viola las reglas de determinismo de XML. Informalmente, estas reglas dicen que el analizador debe saber, sin mirar hacia adelante, qué ficha en el modelo de contenido coincide con cada elemento del documento.Si en un elemento padre el analizador ve un child1, no puede saber sin mirar si acaba de coincidir con la primera o segunda aparición de child1 en el modelo de contenido DevNull. Esto es un error (pero sucede que es un error que los procesadores no están obligados a informar; es un error que significa que "todas las apuestas están desactivadas, el procesador puede hacer cualquier cosa aquí, incluso no darse cuenta de que algo está mal").

Un modelo de contenido para padres que obedece a las reglas determinismo puede estar formado por factorización de prefijos comunes, por lo tanto:

<!ELEMENT parent ( 
        (child1, ((child2,child3) 
          | (child3,child2))) 
       | (child2, ((child1,child3) 
          | (child3,child1))) 
       | (child3, ((child1,child2) 
          | (child2,child1))) 
       ) > 

Esto es menos conveniente que las declaraciones de este modelo puede estar en otros lenguajes de esquema, y para más de tres elementos es propenso a errores y extremadamente tedioso hacerlo a mano. Pero no es imposible declarar el modelo de contenido que desea con las DTD. O quizás debería decir que es imposible solo para los autores de DTD que son incapaces de soportar cualquier inconveniente.

Tenga en cuenta también que a menos que la secuencia de los niños lleva un poco de información, algunas autoridades diseño sostienen firmemente que es mejor para fijar una secuencia.

+0

+1 para una respuesta determinista. –

2

Lectura the spec parece que no se puede.

Cuando los niños se declaran en una secuencia separada por comas, los niños deben aparecer en la misma secuencia en el documento. En una declaración completa, los niños también deben ser declarados, y los niños también pueden tener hijos.

Creo que es porque está declarando una secuencia (o una lista ordenada si lo desea) en lugar de una colección (o una lista desordenada).

+2

Er, el documento que señala no es el [XML spec] (http://www.w3.org/TR/xml). –

9

Probar:

<!ELEMENT parent (child1 | child2 | child3)*> 

debería permitir cero o más de cualquier niño, en cualquier orden.

+0

No creo que esto funcione porque parece que el OP necesitaba los 3 elementos secundarios presentes. Esto se basa en la declaración del OP: "Pero en este caso uno de los niños podría estar perdido, aunque la validación será exitosa". –

+0

Hermosa respuesta. Es genial para lidiar con elementos desordenados de los cuales sabes lo que serán, pero no su orden o cantidad. ¡Gracias @Michael! – zeffii

2

Esto es complicado cuando necesita exactamente uno de los elementos secundarios. Esta es la única forma en que puedo pensar y no es muy bonita. Funciona bien ...

<!ELEMENT parent ( 
       (child1,child2,child3)| 
       (child1,child3,child2)| 
       (child2,child1,child3)| 
       (child2,child3,child1)| 
       (child3,child1,child2)| 
       (child3,child2,child1) 
       )> 

Básicamente, estoy especificando todas las combinaciones posibles de exactamente un elemento child1, child2 y child3.

Aquí hay una instancia de ejemplo. child1, child2 y child3 pueden estar en cualquier orden, pero cada uno debe ocurrir exactamente una vez.

<!DOCTYPE parent [ 
<!ELEMENT parent ( 
       (child1,child2,child3)| 
       (child1,child3,child2)| 
       (child2,child1,child3)| 
       (child2,child3,child1)| 
       (child3,child1,child2)| 
       (child3,child2,child1) 
       )> 
<!ELEMENT child1 (#PCDATA)> 
<!ELEMENT child2 (#PCDATA)> 
<!ELEMENT child3 (#PCDATA)> 
]> 
<parent> 
    <child2></child2> 
    <child1></child1> 
    <child3></child3> 
</parent> 
Cuestiones relacionadas