2010-03-08 12 views
6

Un desafío más para la capacidad de XSD,

He estado enviando archivos XML de mis clientes, que tendrán 0 o más etiquetas indefinidas o [llamadas] inesperadas (pueden aparecer en la jerarquía). Bueno, son etiquetas redundantes para mí ... así que tengo que ignorar su presencia, pero junto con ellas hay un conjunto de etiquetas que se deben validar.¿Cómo ignorar la validación de las etiquetas Desconocidas?

Este es un XML de ejemplo:

<root> 
    <undefined_1>one</undefined_1> 
    <undefined_2>two</undefined_2> 
    <node>to_be_validated</node> 
    <undefined_3>two</undefined_3> 
    <undefined_4>two</undefined_4> 
</root> 

Y el XSD he intentado con:

<xs:element name="root" type="root"></xs:element> 
    <xs:complexType name="root"> 
    <xs:sequence> 
     <xs:any maxOccurs="2" minOccurs="0"/> 
     <xs:element name="node" type="xs:string"/> 
     <xs:any maxOccurs="2" minOccurs="0"/> 
    </xs:sequence> 
    </xs:complexType 

XSD no lo permite, debido a ciertas razones.
El ejemplo mencionado anteriormente es solo una muestra. El XML práctico viene con la compleja jerarquía de etiquetas XML ..

Por favor, hágamelo saber si puede obtener un truco de él.

Por cierto, la solución alternativa es insertar transformación XSL, antes del proceso de validación. Bueno, lo estoy evitando porque necesito cambiar el código .Net que desencadena el proceso de validación, que mi compañía al menos apoya.

+0

¿El problema es que no se valida con el esquema? –

+0

yup .. más bien quería mostrar que "no sé cómo hacerlo ... y lo intenté ESTO" .. –

Respuesta

2

Conclusión:

Esto no es posible con XSD. Todos los enfoques que estaba tratando de lograr el requisito fueron nombrados como "ambiguos" por las herramientas de validación, que acompañan un montón de errores.

1

Tal vez sea posible utilizar espacios de nombres:

<xs:element name="root" type="root"></xs:element> 
    <xs:complexType name="root"> 
    <xs:sequence> 
     <xs:any maxOccurs="2" minOccurs="0" namespace="http://ns1.com" /> 
     <xs:element name="node" type="xs:string"/> 
     <xs:any maxOccurs="2" minOccurs="0" namespace="http://ns2.com"/> 
    </xs:sequence> 
    </xs:complexType> 

Esto probablemente validará.

+0

bien pensado [+1] ... pero desafortunadamente no funciona en mi caso. gracias por la respuesta. :-) –

3

En caso de que su no lo ha hecho con esto, es posible que intente lo siguiente:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xs:element name="root" type="root"></xs:element> 
    <xs:complexType name="root"> 
    <xs:sequence> 
     <xs:any maxOccurs="2" minOccurs="0" processContents="skip"/> 
     <xs:element name="node" type="xs:string"/> 
     <xs:any maxOccurs="2" minOccurs="0" processContents="skip"/> 
    </xs:sequence> 
    </xs:complexType> 
</xs:schema> 

Bajo Linux esto funciona bien con xmllint usando libxml versión 20706.

+0

sin embargo, todavía no permite que el primer elemento sea CUALQUIERA. :( –

+1

¿Cuál es exactamente el problema, por favor? – alk

+0

este es el error que estoy obteniendo: ** comodín '## any' permite elemento 'nodo', y hace que el modelo de contenido se vuelva ambiguo. Tal y tal ** –

1

me enfrenté al mismo problema.

Desde que llamé a la validación de .NET; Decidí suprimir el error de validación específico en ValidationEventHandler como una solución alternativa. Funcionó para mí

private void ValidationEventHandler(object sender, ValidationEventArgs e) 
    { 
     switch (e.Severity) 
     { 
      case XmlSeverityType.Warning: 
       // Processing warnings 
       break; 
      case XmlSeverityType.Error: 
       if (IgnoreUnknownTags 
        && e.Exception is XmlSchemaValidationException 
        && new Regex(
         @"The element '.*' has invalid child element '.*'\." 
         + @" List of possible elements expected:'.*'\.") 
         .IsMatch(e.Exception.Message)) 
       { 
        return; 
       } 
       // Processing errors 
       break; 
      default: 
       throw new InvalidEnumArgumentException("Severity should be one of the valid values"); 
     } 
    } 

Es importante que Thread.CurrentUICulture se debe establecer en Inglés o CultureInfo.InvariantCulture para el subproceso actual para que esto funcione.

0

Puede utilizar una nueva función en XML 1.1 llamada "Contenido abierto". En resumen, le permite especificar que se pueden agregar elementos "desconocidos" adicionales a un tipo complejo en varias posiciones y lo que el analizador debería hacer si toca alguno de esos elementos

Usando XML 1.1, su tipo complejo se convertiría en:

<xs:element name="root" type="root" /> 
<xs:complexType name="root"> 
    <xs:openContent mode="interleave"> 
    <xs:any namespace="##any" processContents="skip"/> 
    </xs:openContent> 

    <xs:sequence> 
    <xs:element name="node" type="xs:string"/> 
    </xs:sequence> 
</xs:complexType> 

Si usted tiene una gran cantidad de tipos complejos, también puede establecer un modo de contenido abierto "por defecto" en la parte superior de su esquema:

<xs:schema ...> 
    <xs:defaultOpenContent mode="interleave"> 
    <xs:any namespace="##any" processContents="skip"/> 
    </xs:defaultOpenContent> 

    ... 
</xs:schema> 

El Las especificaciones de W3C para contenido abierto se pueden encontrar en http://www.w3.org/TR/xmlschema11-1/#oc y hay una buena descripción de esto en http://www.ibm.com/developerworks/library/x-xml11pt3/#N102BA.

Por desgracia, no es compatible con .NET XML 1.1 hasta el momento no puedo encontrar ningún procesadores XML 1.1 gratis - pero un par de opciones de pago para son:

Cuestiones relacionadas