Question

Notre application C ++ lit les données de configuration à partir de fichiers XML qui ressemble à quelque chose comme ceci:

<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 configuration de l'application complète se composent de ~ 2500 de ces fichiers XML (ce qui se traduit plus de 1,5 million de clé / valeur d'attribut paires). Les fichiers XML proviennent de nombreuses sources / équipes et sont validées par rapport à un schéma. Cependant, parfois les nœuds <value/> ressemblent à ceci:

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

ou ceci:

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

Pour rendre ce processus rapide, nous utilisons Expat pour analyser les documents XML. Expat expose les attributs comme un tableau - comme ceci:

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);
 }
}

Cela met toute la responsabilité sur notre fonction ProcessAttribute() pour lire la « clé » et de décider quoi faire avec la valeur. Profilage l'application a montré que ~ 40% du temps total XML Parsing traite de ces attributs par nom / string.

Le processus global pourrait être accéléré de façon spectaculaire si je pouvais garantir / faire respecter l'ordre des attributs (pour commencer, pas de comparaisons de chaîne dans ProcessAttribute()). Par exemple, si l'attribut « id » était toujours le 1er attribut que nous pourrions traiter directement:

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

Selon les spécifications du schéma W3C, je peux utiliser <xs:sequence> dans un schéma XML pour appliquer l'ordre des éléments - mais il ne semble pas fonctionner pour les attributs - ou peut-être que je l'utilise de manière incorrecte:

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

Yat-il un moyen de faire respecter l'ordre d'attribut dans un document XML? Si la réponse est « non » - pourrait-on suggérer peut-être une alternative qui ne serait pas passible d'une peine énorme performance d'exécution

Était-ce utile?

La solution

Selon la spécification XML,

  

l'ordre des spécifications d'attributs dans une balise de début ou balise vide-élément est non significatif

Vous pouvez vérifier à section 3.1

Autres conseils

Les attributs XML ne pas Vous un ordre, donc il n'y a pas d'ordre à appliquer.

Si vous voulez quelque chose commandé, vous avez besoin d'éléments XML. Ou quelque chose de différent de XML. JSON, YAML et bencode, par exemple, avoir les deux cartes (qui sont non ordonnée) et les séquences (qui sont commandées).

Comme d'autres l'ont souligné, non, vous ne pouvez pas compter sur commande d'attribut.

Si, dès que je pouvais peut-être que j'avais tout processus tout impliquant 2500 fichiers XML et 1,5 million de paires clé / valeur, je recevrais que les données sur XML et sous une forme plus utilisable. Une base de données, un format de sérialisation binaire, peu importe. Vous n'êtes pas obtenir un avantage sur l'utilisation de XML (autre que la validation du schéma). Je mets à jour mon magasin chaque fois que je suis un nouveau fichier XML, et prendre l'analyse de 1,5 million d'éléments XML hors du flux principal de mon processus.

La réponse est non, hélas. Je suis choqué par votre chiffre de 40%. Je trouve difficile de croire que tourner « foo » dans ProcessFoo prend longtemps. Êtes-vous sûr que le 40% ne comprend pas le temps nécessaire pour exécuter ProcessFoo?

Est-il possible d'accéder aux attributs par nom en utilisant cette chose Expat? C'est la façon plus traditionnelle pour accéder aux attributs. Je ne dis pas que ça va être plus rapide, mais il pourrait être la peine d'essayer.

Je ne pense pas que le schéma XML soutient que - les attributs sont simplement définis et limités par nom, par exemple ils doivent correspondre à un nom particulier - mais je ne vois pas comment vous pouvez définir un ordre pour les attributs XSD

.

Je ne connais aucune autre façon de faire des attributs sûr sur un noeud XML viennent dans un ordre particulier - pas sûr si l'un des autres mécanismes de schéma XML comme Schematron ou Relax NG soutiendrait que ....

Je suis assez sûr qu'il n'y a pas moyen de faire respecter l'ordre d'attribut dans un document XML. Je vais supposer que vous pouvez insister sur ce point par l'intermédiaire d'un processus d'affaires ou d'autres facteurs humains, comme un contrat ou tout autre document.

Et si vous venez supposé que le premier attribut était « id », et testé le nom pour être sûr? Si oui, utilisez la valeur, sinon, vous pouvez essayer d'obtenir l'attribut par nom ou jeter le document.

Bien que pas aussi efficace que d'appeler à l'attribut par son ordinal, un nombre non nul de fois que vous serez en mesure de deviner que vos fournisseurs de données ont livré aux spécifications XML. Le reste du temps, vous pouvez prendre d'autres mesures.

Juste une supposition, mais pouvez-vous essayer d'ajouter use="required" à chacun de vos spécifications d'attributs?

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

Je me demande si l'analyseur est ralenti en permettant des attributs facultatifs, quand il apparaît vos attributs seront toujours là.

Encore une fois, juste une supposition.

EDIT: spécifications XML 1.0 indique que l'ordre d'attribut est non significatif. http://www.w3.org/TR/REC-xml/# sec-starttags

Par conséquent, XSD ne faire exécuter une ordonnance. Mais cela ne signifie pas que les parseurs ne peuvent pas être dupes en travaillant rapidement, donc je garde la réponse publiée ci-dessus dans le cas où il fonctionne réellement.

D'après ce que je me souviens, Expat est un analyseur non validation et de mieux pour elle .. donc vous pouvez probablement la ferraille cette idée XSD. Ni est une bonne idée en fonction de l'ordre dans de nombreuses approches XML (XSD obtenu a critiqué l'ordre des éléments d'un diable de beaucoup dans la journée, par exemple, par les vendeurs pro ou anti de services Web XML à MSFT).

Faites votre codage personnalisé et simplement étendre soit votre logique pour la recherche plus efficace ou creuser dans la source de l'analyseur. Il est trivial d'écrire l'outillage autour de codage de remplacement efficace tout en protégeant les agents logiciels et les utilisateurs de ce que vous voulez .. faire ce donc il est facilement migré tout en préservant la compatibilité descendante et la réversibilité. De plus, optez pour des contraintes de taille fixe / attribute-name-traduction.

[Considérez-vous chanceux avec Expat :) et sa vitesse brute. Imaginez comment devs CLR aiment les installations de mise à l'échelle XML, ils envoient régulièrement 200MB sur le fil dans le processus de « juste interrogation de la base » ..]

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top