2009-11-05 11 views
17
aplicación

Nuestra C++ lee los datos de configuración de archivos XML que ser algo como esto:¿Puedo hacer cumplir el orden de los atributos XML utilizando un esquema?

<data> 
<value id="FOO1" name="foo1" size="10" description="the foo" ... /> 
<value id="FOO2" name="foo2" size="10" description="the other foo" ... /> 
... 
<value id="FOO300" name="foo300" size="10" description="the last foo" ... /> 
</data> 

La configuración de la aplicación completa consisten en ~ 2500 de estos archivos XML (que se traduce en más de 1,5 millones de clave/valor pares de atributos) . Los archivos XML provienen de diferentes fuentes/equipos y se validan contra un esquema. Sin embargo, a veces los nodos <value/> este aspecto:

<value name="bar1" id="BAR1" description="the bar" size="20" ... /> 

o esto:

<value id="BAT1" description="the bat" name="bat1" size="25" ... /> 

Para hacer este proceso rápido, estamos utilizando Expat para analizar los documentos XML. Expatriados expone los atributos como un conjunto - como este:

void ExpatParser::StartElement(const XML_Char* name, const XML_Char** atts) 
{ 
// The attributes are stored in an array of XML_Char* where: 
// the nth element is the 'key' 
// the n+1 element is the value 
// the final element is NULL 
for (int i = 0; atts[i]; i += 2) 
{ 
    std::string key = atts[i]; 
    std::string value = atts[i + 1]; 
    ProcessAttribute (key, value); 
} 
} 

Esto pone toda la responsabilidad a nuestra función ProcessAttribute() a leer la 'llave' y decidir qué hacer con el valor. La creación de perfiles de la aplicación ha demostrado que ~ 40% del tiempo total de análisis XML trata estos atributos por nombre/cadena.

El proceso general podría acelerarse drásticamente si pudiera garantizar/hacer cumplir el orden de los atributos (para los principiantes, no hay comparaciones de cadenas en ProcessAttribute()). Por ejemplo, si el atributo 'id' era siempre la primera atributo que podría tratar con él directamente:

void ExpatParser::StartElement(const XML_Char* name, const XML_Char** atts) 
{ 
// The attributes are stored in an array of XML_Char* where: 
// the nth element is the 'key' 
// the n+1 element is the value 
// the final element is NULL 
ProcessID (atts[1]); 
ProcessName (atts[3]); 
//etc. 
} 

De acuerdo con las especificaciones de esquema del W3C, puedo usar <xs:sequence> en un esquema XML para hacer cumplir la orden de los elementos - pero no parece trabajar por atributos - o tal vez lo estoy usando incorrectamente:

<xs:element name="data"> 
<xs:complexType> 
    <xs:sequence> 
    <xs:element name="value" type="value_type" minOccurs="1" maxOccurs="unbounded" /> 
    </xs:sequence> 
</xs:complexType> 
</xs:element> 

<xs:complexType name="value_type"> 
<!-- This doesn't work --> 
<xs:sequence> 
    <xs:attribute name="id" type="xs:string" /> 
    <xs:attribute name="name" type="xs:string" /> 
    <xs:attribute name="description" type="xs:string" /> 
</xs:sequence> 
</xs:complexType> 

¿hay una manera de hacer cumplir el orden atributo en un documento XML? Si la respuesta es "no", ¿alguien podría sugerir una alternativa que no conlleve una gran penalización de rendimiento en el tiempo de ejecución?

+2

Por qué fue usted con atributos y no foo1 foo1 Esta es la descripción? Puede especificar el orden de los elementos, entonces, ¿por qué no usarlos? – jmucchiello

+0

+1 Esta es una pregunta muy bien escrita (e interesante). –

Respuesta

30

De acuerdo con la especificación XML,

el orden de las especificaciones de atributo en una etiqueta de comienzo o etiqueta de elemento vacío no es significativo

Usted puede comprobarlo en section 3.1

1

No creo que XML Schema lo admita: los atributos solo se definen y se restringen por su nombre, p. Ej. tienen que coincidir con un nombre particular, pero no veo cómo se podría definir un orden para esos atributos en XSD.

No conozco ninguna otra forma de asegurarme de que los atributos en un nodo XML vienen en un orden en particular, no estoy seguro si alguno de los otros esquemas XML mecanismos como Schematron o Relax NG soportarían eso ....

+4

No es una restricción del esquema XML, sino del propio XML. Ver el comentario de st.stoqnov. – porges

0

Solo supongo, pero ¿puedes intentar agregar use="required" a cada una de las especificaciones de tus atributos?

<xs:complexType name="value_type"> 
<!-- This doesn't work --> 
<xs:sequence> 
    <xs:attribute name="id" type="xs:string" use="required" /> 
    <xs:attribute name="name" type="xs:string" use="required" /> 
    <xs:attribute name="description" type="xs:string" use="required" /> 
</xs:sequence> 
</xs:complexType> 

Me pregunto si el analizador está siendo frenado por permitir atributos opcionales, cuando aparece sus atributos siempre estarán ahí.

Nuevamente, solo una conjetura.

EDITAR: La especificación XML 1.0 dice que el orden de los atributos no es significativo. http://www.w3.org/TR/REC-xml/#sec-starttags

Por lo tanto, XSD no aplicará ninguna orden.Pero eso no significa que no se pueda engañar a los analizadores para que funcionen rápidamente, por lo que mantengo la respuesta anterior publicada en caso de que realmente funcione.

1

Estoy bastante seguro de que no hay forma de imponer el orden de los atributos en un documento XML. Voy a suponer que puede insistir en ello a través de un proceso comercial u otros factores humanos, como un contrato u otro documento.

¿Qué pasa si simplemente asumió que el primer atributo era "id" y probó el nombre para estar seguro? En caso afirmativo, utilice el valor, de lo contrario, puede tratar de obtener el atributo por su nombre o arrojar el documento.

Si bien no es tan eficiente como llamar el atributo por su ordinal, algunas veces no es cero, podrá adivinar que sus proveedores de datos han entregado XML a las especificaciones. El resto del tiempo, puedes tomar otra acción.

2

La respuesta es no, alas. Estoy sorprendido por tu 40% de figura. Me resulta difícil creer que convertir "foo" en ProcessFoo toma tanto tiempo. ¿Estás seguro de que el 40% no incluye el tiempo necesario para ejecutar ProcessFoo?

¿Es posible acceder a los atributos por nombre usando este objeto de Expansión? Esa es la manera más tradicional de acceder a los atributos. No digo que vaya a ser más rápido, pero podría valer la pena intentarlo.

+2

'Expat thing' es uno de los analizadores más rápidos de todo ... No se sorprenda, acaba de ser vendido XML por MSFT e IBM y no escala :-) –

+1

Gary, tiene razón. No expliqué exactamente qué hace la función ProccessAttribute() porque pensé que estaba fuera del tema de la pregunta original ... Estamos analizando estos documentos XML en el inicio de la aplicación y volcamos los datos del elemento en una base de datos sqlite para su posterior procesamiento . La API sqlite permite el enlace de parámetros por índice, por lo que si pudiera confiar en que los atributos XML siempre estuvieran en el mismo orden que los parámetros en la declaración Insert, las cosas irían mucho (mucho) más rápido. –

0

Por lo que recuerdo, Expat es un analizador no validador y mejor para él ... por lo que probablemente puedas descartar esa idea de XSD. Tampoco es una buena idea depender de la orden en muchos enfoques XML (XSD fue criticado en el orden de los elementos mucho atrás en el día, por ejemplo, por los profesionales o antisubmarinos de XML Web Services en MSFT).

Realice su codificación personalizada y simplemente amplíe su lógica para una búsqueda más eficiente o explore la fuente del analizador. Es trivial escribir las herramientas alrededor de la codificación de reemplazo eficiente mientras se protegen los agentes de software y los usuarios de él ... lo que se desea hacer es migrar fácilmente mientras se preserva la retrocompatibilidad y la reversibilidad. Además, opta por restricciones de tamaño fijo/nombre-atributo-traducción.

[Considérese afortunado con Expat :) y su velocidad bruta. Imaginar cómo los desarrolladores CLR aman instalaciones de escala XML, que habitualmente envían 200 MB en el alambre en proceso de 'sólo la consulta de la base de datos' ..]

6

atributos XML no tienen un pedido, por lo tanto, no hay fin de hacer cumplir .

Si quiere algo ordenado, necesita elementos XML. O algo diferente de XML. JSON, YAML y bEncode, p. tener ambos mapas (que están desordenados) y secuencias (que están ordenadas).

4

Como han señalado otros, no, no puede confiar en el orden de los atributos.

Si tuviera cualquier proceso que involucre 2.500 archivos XML y 1.5 millones de pares clave/valor, obtendría esos datos de XML y en una forma más utilizable tan pronto como pudiera. Una base de datos, un formato de serialización binario, lo que sea.No obtiene ninguna ventaja de usar XML (que no sea la validación de esquema). Actualizaba mi tienda cada vez que obtenía un nuevo archivo XML y analizaba el análisis de 1,5 millones de elementos XML del flujo principal de mi proceso.

Cuestiones relacionadas