with validator validate validar test online characters archivo xml xsd xml-validation

validate - xml validator xsd



Validar XML con XSD... pero aún permitir la extensibilidad (5)

Tal vez soy yo, pero parece que si tienes un XSD

<?xml version="1.0" encoding="utf-8"?> <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="User"> <xs:complexType> <xs:sequence> <xs:element name="GivenName" /> <xs:element name="SurName" /> </xs:sequence> <xs:attribute name="ID" type="xs:unsignedByte" use="required" /> </xs:complexType> </xs:element> </xs:schema>

eso define el esquema para este documento

<?xml version="1.0" encoding="utf-8" ?> <User ID="1"> <GivenName></GivenName> <SurName></SurName> </User>

No se puede validar si agregó otro elemento, por ejemplo, EmailAddress, y se mezcla la orden

<?xml version="1.0" encoding="utf-8" ?> <User ID="1"> <SurName></SurName> <EmailAddress></EmailAddress> <GivenName></GivenName> </User>

No deseo agregar EmailAddress al documento y que se marque como opcional.

Solo quiero un XSD que valide los requisitos mínimos que el documento debe cumplir.

¿Hay alguna forma de hacer esto?

EDITAR:

marc_s señaló a continuación que puede usar xs:any dentro de xs:sequence para permitir más elementos, desafortunadamente, debe mantener el orden de los elementos.

Alternativamente, puedo usar xs:all cual no impone el orden de los elementos, pero desafortunadamente no me permite colocar xs:any dentro de él.


Bueno, siempre puedes usar DTD :-) excepto que DTD también prescribe el orden. La validación con gramática "desordenada" es terriblemente costosa. Podrías jugar con xsd: choice y min y max ocurriría, pero probablemente también lo haga. También puede escribir extensiones XSD / esquemas derivados.

La forma en que planteaste el problema parece que en realidad no quieres XSD en absoluto. Puedes simplemente cargarlo y luego validar el mínimo que quieras con XPaths, pero solo protestar contra XSD, cuántos años después se convirtió en omnipresente, el estándar realmente no te va a llevar a ninguna parte.


Debería poder extender su esquema con el elemento <xs:any> para la extensibilidad - vea W3Schools para más detalles.

<?xml version="1.0" encoding="utf-8"?> <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="User"> <xs:complexType> <xs:sequence> <xs:element name="GivenName" /> <xs:element name="SurName" /> <xs:any minOccurs="0" maxOccurs="unbounded" processContents="lax" /> </xs:sequence> <xs:attribute name="ID" type="xs:unsignedByte" use="required" /> </xs:complexType> </xs:element> </xs:schema>

Cuando agrega processContents="lax" , la validación de .NET XML debería tener éxito.

Consulte los documentos de MSDN en xs: any para obtener más detalles.

Actualización: si necesita más flexibilidad y una validación menos estricta, le relaxng.org que consulte otros métodos de definición de esquemas para su XML, como relaxng.org . XML Schema es, a propósito, bastante estricto con sus reglas, por lo que tal vez sea la herramienta incorrecta para este trabajo.


Después de leer la respuesta de marc_s y su discusión en comentarios, decido agregar un poco.

Me parece que no hay una solución perfecta para su problema, Chad . Hay algunos enfoques sobre cómo implementar un modelo de contenido extensible en XSD, pero toda mi implementación conocida tiene algunas restricciones. Como no escribió sobre el entorno en el que planea usar XSD extensible, solo puede recomendar algunos enlaces que probablemente le ayuden a elegir la forma en que se puede implementar en su entorno:

  1. http://www.xfront.com/ExtensibleContentModels.html (o http://www.xfront.com/ExtensibleContentModels.pdf ) y http://www.xfront.com/VariableContentContainers.html
  2. http://www.xml.com/lpt/a/993 (o http://www.xml.com/pub/a/2002/07/03/schema_design.html )
  3. http://msdn.microsoft.com/en-us/library/ms950793.aspx

RelaxNG resolverá este problema de manera sucinta, si puede usarlo. El determinismo no es un requisito para los esquemas. Puede traducir un esquema RNG o RNC en XSD, pero se aproximará en este caso. Si eso es lo suficientemente bueno para su uso depende de usted.

El esquema RNC para este caso es:

start = User User = element User { attribute ID { xsd:unsignedByte }, ( element GivenName { text } & element SurName { text } & element * - (SurName | GivenName) { any }) } any = element * { (attribute * { text } | text | any)* }

La regla coincide con cualquier fragmento XML bien formado. Por lo tanto, esto requerirá que el elemento User contenga los elementos GivenName y SurName que contengan texto en cualquier orden, y permita cualquier otro elemento que contenga casi cualquier cosa.


Tu problema tiene una resolución, pero no será bonita. Este es el por qué:

Violación de modelos de contenido no deterministas

Has tocado el alma de W3C XML Schema. Lo que estás preguntando - orden variable y elementos variables desconocidos - viola el principio más duro, aunque más básico, de los XSD, la regla de no ambigüedad o, más formalmente, la restricción de atribución de partículas únicas :

Un modelo de contenido debe formarse de modo que durante la validación [..] cada elemento de la secuencia se pueda determinar de manera única sin examinar el contenido o los atributos de ese elemento, y sin ninguna información sobre los elementos en el resto de la secuencia.

En inglés normal: cuando se valida un XML y el procesador XSD encuentra <SurName> , debe poder validarlo sin verificar primero si está seguido por <GivenName> , es decir, sin mirar hacia adelante. En su escenario, esto no es posible. Esta regla existe para permitir implementaciones a través de máquinas de estados finitos, lo que debería hacer que las implementaciones sean bastante triviales y rápidas.

Este es uno de los temas más debatidos y es un patrimonio de SGML y DTD (los modelos de contenido deben ser deterministas ) y XML, que define, de forma predeterminada, que el orden de los elementos es importante (por lo tanto, intentar lo contrario, realizar el pedido sin importancia, es difícil).

Como Marc_s ya sugirió, Relax_NG es una alternativa que permite modelos de contenido no deterministas. Pero, ¿qué puede hacer si está atascado con el esquema XML de W3C?

Soluciones semi-válidas que no funcionan

Ya has notado que xs:all es muy restrictivo. La razón es simple: se aplica la misma regla no determinista y es por eso que xs:any , min/maxOccurs mayor que uno y las secuencias no están permitidas.

Además, puede haber intentado todo tipo de combinaciones de choice , sequence y any . El error que arroja el procesador Microsoft XSD cuando se encuentra con una situación no válida es:

Error: la definición múltiple del elemento '' http://example.com/Chad:SurName '' hace que el modelo de contenido se vuelva ambiguo. Un modelo de contenido debe formarse de modo que durante la validación de una secuencia de elemento de información de elemento, la partícula contenida directa, indirecta o implícitamente con la que intentar validar cada elemento en la secuencia a su vez pueda determinarse de manera única sin examinar el contenido o atributos de ese artículo, y sin ninguna información sobre los artículos en el resto de la secuencia.

En el Esquema XML de O''Reilly (sí, el libro tiene sus fallas) esto se explica de manera excelente. Por suerte, partes del libro están disponibles en línea. Le recomiendo que lea la sección 7.4.1.3 sobre la Regla única de atribución de partículas , sus explicaciones y ejemplos son mucho más claros de lo que puedo obtenerlos.

Una solución de trabajo

En la mayoría de los casos, es posible pasar de un diseño indeterminado a un diseño determinista. Por lo general, esto no se ve bonito, pero es una solución si tiene que seguir con el Esquema XML de W3C y / o si debe permitir absolutamente reglas no estrictas para su XML. La pesadilla de su situación es que desea aplicar una cosa (2 elementos predefinidos) y, al mismo tiempo, desea tenerla muy suelta (el orden no importa y todo puede ir entre, antes y después). Si no trato de darle un buen consejo, sino que lo lleve directamente a una solución, se verá de la siguiente manera:

<xs:element name="User"> <xs:complexType> <xs:sequence> <xs:any minOccurs="0" processContents="lax" namespace="##other" /> <xs:choice> <xs:sequence> <xs:element name="GivenName" /> <xs:any minOccurs="0" processContents="lax" namespace="##other" /> <xs:element name="SurName" /> </xs:sequence> <xs:sequence> <xs:element name="SurName" /> <xs:any minOccurs="0" processContents="lax" namespace="##other" /> <xs:element name="GivenName" /> </xs:sequence> </xs:choice> <xs:any minOccurs="0" processContents="lax" namespace="##any" /> </xs:sequence> <xs:attribute name="ID" type="xs:unsignedByte" use="required" /> </xs:complexType> </xs:element>

El código de arriba simplemente funciona . Pero hay algunas advertencias. El primero es xs:any con ##other como su espacio de nombres. No puede usar ##any , excepto el último, porque eso permitiría que elementos como GivenName se usen en ese lugar y eso significa que la definición de User vuelve ambigua.

La segunda advertencia es que si quieres usar este truco con más de dos o tres, tendrás que anotar todas las combinaciones. Una pesadilla de mantenimiento. Es por eso que se me ocurre lo siguiente:

Una solución sugerida, una variante de un contenedor de contenido variable

Cambia tu definición Esto tiene la ventaja de ser más claro para sus lectores o usuarios. También tiene la ventaja de ser más fácil de mantener. Aquí se explica toda una serie de soluciones en XFront , un enlace menos legible que ya puede haber visto en la publicación de Oleg. Es una lectura excelente, pero la mayoría no tiene en cuenta que tiene un requisito mínimo de dos elementos dentro del contenedor de contenido variable.

El enfoque actual de mejores prácticas para su situación (que ocurre con más frecuencia de lo que imagina) es dividir sus datos entre los campos requeridos y no requeridos. Puede agregar un elemento <Required> , o hacer lo contrario, agregar un elemento <ExtendedInfo> (o llamarlo Propiedades , o Datos opcionales ). Esto se ve de la siguiente manera:

<xs:element name="User2"> <xs:complexType> <xs:sequence> <xs:element name="GivenName" /> <xs:element name="SurName" /> <xs:element name="ExtendedInfo" minOccurs="0"> <xs:complexType> <xs:sequence> <xs:any minOccurs="0" maxOccurs="unbounded" processContents="lax" namespace="##any" /> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element>

Esto puede parecer menos que ideal en este momento, pero déjelo crecer un poco. Tener un conjunto ordenado de elementos fijos no es gran cosa. No es el único que se quejará de esta aparente deficiencia del esquema W3C XML, pero como dije antes, si tiene que usarlo, tendrá que vivir con sus limitaciones o aceptar la carga de desarrollar alrededor de estas limitaciones a un mayor costo de propiedad.

Solución alternativa

Estoy seguro de que ya lo sabes, pero el orden de los atributos no está determinado de manera predeterminada. Si todo su contenido es de tipos simples, alternativamente puede optar por hacer un uso más abundante de los atributos.

Una última palabra

Independientemente del enfoque que tome, perderá mucha verificabilidad de sus datos. A menudo es mejor permitir que los proveedores de contenido agreguen tipos de contenido, pero solo cuando se pueda verificar. Esto se puede hacer pasando del procesamiento lax al strict y haciendo que los tipos sean más estrictos. Pero ser demasiado estricto tampoco es bueno, el equilibrio correcto dependerá de su capacidad para juzgar los casos de uso contra los que se enfrenta y sopesando las ventajas y desventajas de ciertas estrategias de implementación.