Pregunta

Nuestra C ++ aplicación lee los datos de configuración de archivos XML que ser algo como esto:

<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 consiste de ~ 2500 de estos archivos XML (que se traduce en más de 1,5 millones de clave / valor de atributo pares). Los archivos XML provienen de muchas fuentes diferentes y / equipos se validan con 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 que este proceso sea rápido, estamos utilizando expatriado para analizar los documentos XML. Expatriados expone los atributos como un conjunto - como esto:

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. Perfiles de la aplicación ha demostrado que ~ 40% del tiempo total de análisis XML está tratando con estos atributos por nombre / cadena.

El proceso global podría ser acelerado dramáticamente si podía garantizar / hacer cumplir la orden de los atributos (para empezar, no hay comparaciones de cadenas en ProcessAttribute()). Por ejemplo, si el atributo 'id' fue siempre la primera atributo podríamos 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 funcionar para los 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 quizá sugerir una alternativa que no llevaría a una enorme pérdida de rendimiento en tiempo de ejecución

¿Fue útil?

Solución

De acuerdo con la especificación XML,

  

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

Puede comprobarlo en sección 3.1

Otros consejos

atributos XML no Tienes una orden, por lo tanto, no hay fin de hacer cumplir.

Si quieres algo ordenado, necesita elementos XML. O algo diferente de XML. JSON, YAML y bEncode, por ejemplo tener ambos mapas (que son no ordenada) y secuencias (que están ordenados).

Como otros han señalado, no, no se puede confiar en la ordenación de atributos.

Si tuviera cualquier proceso que involucra a todos los archivos XML 2.500 y 1,5 millones de pares clave / valor, conseguiría que los datos de XML y en una forma más fácil de usar tan pronto como me fuera posible. Una base de datos, un formato de serialización binaria, lo que sea. Que no está recibiendo ninguna ventaja de utilizar XML (que no sea la validación del esquema). Me actualizo mi tienda cada vez que llegaba un nuevo archivo XML, y tomo analizar 1,5 millones de elementos XML fuera de la corriente principal de mi proceso.

La respuesta es no, por desgracia. Estoy muy sorprendida por su figura 40%. Me resulta difícil creer que girar "foo" en ProcessFoo necesita ese tiempo. ¿Estás seguro de que el 40% no incluye el tiempo necesario para ejecutar ProcessFoo?

¿Es posible acceder a los atributos de nombre utilizando esta cosa expatriado? Esa es la forma más tradicional para acceder a atributos. No estoy diciendo que va a ser más rápido, pero podría valer la pena probar.

No creo que el esquema XML que soporta - atributos simplemente se definen y limitan por su nombre, por ejemplo, tienen que coincidir con un nombre en particular - pero no veo cómo se puede definir un pedido de esos atributos en XSD

.

No sé de ninguna otra manera de hacer seguro atributos en un nodo XML llegado en un orden particular - no está seguro de si alguno de los otros mecanismos de esquema XML como Schematron o Relax NG apoyaría que ....

Estoy bastante seguro de que no hay manera de hacer cumplir el orden atributo en un documento XML. Voy a suponer que usted puede insistir en él a través de un proceso de negocio o de otros factores humanos, tales como un contrato u otro documento.

¿Y si asumimos que el primer atributo era "id", y probó el nombre para estar seguro? Si es así, utilice el valor, si no, entonces usted puede tratar de obtener el atributo de nombre o tirar el documento.

Aunque no es tan eficiente como llamar a cabo el atributo por su ordinal, un número distinto de cero de veces que va a ser capaz de adivinar que sus proveedores de datos han entregado a las especificaciones XML. El resto del tiempo, se puede tomar otra acción.

Sólo una conjetura, pero se puede probar a añadir use="required" a cada uno de sus especificaciones de atributo?

<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í.

Una vez más, sólo una suposición.

EDIT: XML especificación 1.0 dice que el orden atributo no es significativo. http://www.w3.org/TR/REC-xml/# sec-starttags

Por lo tanto, XSD no hará cumplir cualquier orden. Pero eso no quiere decir que los programas de análisis no se puede engañar a trabajar rápidamente, así que me quedo con la respuesta anterior publicada en caso de que realmente funciona.

De lo que recuerdo, Expatriado es un analizador de validación no y mejor para ella .. por lo que probablemente puede desechar esa idea XSD. Ninguno de los dos es el orden dependiente de una buena idea en muchos enfoques XML (XSD consiguió criticado el orden de los elementos de una diablos de un montón de vuelta en el día, por ejemplo, por los vendedores pro o anti de servicios Web XML en MSFT).

Haga su codificación personalizada y simplemente extender su lógica, ya sea para la búsqueda más eficiente o excavar en la fuente analizador. Es trivial para escribir el utillaje alrededor sustitución eficiente de codificación, mientras que el blindaje de los agentes de software y usuarios de ella .. desea hacer para esto por lo que se migra fácilmente preservando al mismo tiempo la compatibilidad hacia atrás y reversibilidad. También, ir a las limitaciones de tamaño fijo / nombre-atributo-traducción.

[Considérese afortunado con expatriados :) y su velocidad pura. 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' ..]

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top