Domanda

La nostra applicazione C ++ legge i dati di configurazione da file XML che aspetto simile a questo:

<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 configurazione completa applicazione sono costituiti da ~ 2500 di questi file XML (che si traduce in più di 1,5 milioni di chiave / valore attributo coppie). I file XML vengono da diversi fonti / team e vengono convalidati rispetto a uno schema. Tuttavia, a volte i nodi <value/> simile a questa:

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

o questo:

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

Per rendere questo processo veloce, stiamo utilizzando Expat per analizzare i documenti XML. Expat espone gli attributi come array - in questo modo:

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

Questo mette la piena responsabilità sul nostro funzione ProcessAttribute() di leggere la 'chiave' e decidere cosa fare con il valore. Profiling l'applicazione ha dimostrato che circa il 40% del tempo totale di parsing XML a che fare con questi attributi per nome / string.

Il processo complessivo potrebbe essere accelerato in modo drammatico se potevo garantire / rispettare l'ordine degli attributi (per cominciare, nessun confronti di stringhe in ProcessAttribute()). Per esempio, se l'attributo 'id' stato sempre il primo attributo che potremmo affrontare direttamente:

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

Secondo le specifiche dello schema W3C, posso usare <xs:sequence> in uno schema XML per far rispettare l'ordine degli elementi - ma non sembra funzionare per gli attributi - o forse lo sto usando in modo non corretto:

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

C'è un modo per far rispettare ordine di attributo in un documento XML? Se la risposta è "no" -? Qualcuno potrebbe forse suggerire un'alternativa che non avrebbe portato un enorme penalizzazione delle prestazioni di runtime

È stato utile?

Soluzione

In base alla specifica XML,

  

l'ordine di specifiche di attributi in una start-tag o tag di elemento vuoto non è significativo

È possibile controllare a sezione 3.1

Altri suggerimenti

attributi XML non sono un ordine, quindi non c'è fine di far rispettare.

Se si desidera qualcosa di ordinato, è necessario elementi XML. O qualcosa di diverso da XML. JSON, YAML e bEncode, ad esempio avere entrambe le mappe (che sono non ordinate) e le sequenze (che vengono ordinati).

Come altri hanno fatto notare, no, non si può fare affidamento su ordinazione attributo.

Se avessi avuto alcun processo a tutti che coinvolge 2.500 file XML e 1,5 milioni di coppie chiave / valore, vorrei ottenere che i dati da XML e in una forma più utilizzabile non appena mi fosse possibile. Un database, un formato di serializzazione binaria, qualsiasi cosa. Non stai ricevendo alcun vantaggio di utilizzare XML (diverso convalida dello schema). Vorrei aggiornare il mio negozio ogni volta che ho avuto un nuovo file XML, e prendo l'analisi 1,5 milioni di elementi XML fuori dal flusso principale del mio processo.

La risposta è no, ahimè. Sono scioccato dalla vostra figura 40%. Trovo difficile credere che svolta "pippo" in ProcessFoo prende così a lungo. Sei sicuro che il 40% non comprende il tempo necessario per execute ProcessFoo?

E 'possibile accedere agli attributi per nome utilizzando questa cosa all'estero? Questo è il modo più tradizionale per accedere agli attributi. Non sto dicendo che sta per essere più veloce, ma potrebbe essere la pena di provare.

Non credo XML Schema sostiene che - attributi sono semplicemente definiti e limitati per nome, per esempio essi devono corrispondere un nome particolare - ma non vedo come si potrebbe definire un ordine per tali attributi in XSD

.

Non conosco nessun altro modo per assicurarsi che gli attributi in un nodo XML entrare in un ordine particolare - non so se uno qualsiasi degli altri meccanismi di schema XML come Schematron o Relax NG sosterrebbe che ....

Sono abbastanza sicuro che non c'è modo di far rispettare al fine di attributo in un documento XML. Ho intenzione di assumere che si può insistere su di esso tramite un processo di business o di altri fattori umani, come un contratto o altro documento.

Che cosa succede se si appena assunto che il primo attributo era "id", e testato il nome per essere sicuri? Se sì, utilizzare il valore, se non, allora si può cercare di ottenere l'attributo per nome o buttare via il documento.

Anche se non è così efficiente come chiamando l'attributo dal suo numero ordinale, un determinato numero di volte diverso da zero sarete in grado di indovinare che i fornitori di dati XML hanno consegnato a spec. Il resto del tempo, si può prendere altre azioni.

Solo una supposizione, ma si può provare ad aggiungere use="required" a ciascuna delle vostre specifiche degli attributi?

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

Mi chiedo se il parser viene rallentato, consentendo attributi opzionali, quando appare tuoi attributi saranno sempre lì.

Anche in questo caso, solo una supposizione.

Modifica XML 1.0 specifiche dice che l'ordine attributo non è significativo. http://www.w3.org/TR/REC-xml/# sec-starttags

Quindi, XSD non applicherà alcun ordine. Ma questo non significa che i parser non possono essere ingannati a lavorare in fretta, così mi tengo la risposta di cui sopra pubblicato nel caso in cui esso funziona realmente.

Da quello che mi ricordo, Expat è un parser di convalida non e meglio per esso .. quindi probabilmente si può scartare che XSD idea. Né è l'ordine-dipendente una buona idea in molti approcci XSD (XML ottenuto criticato su ordine elemento un diavolo di un sacco di nuovo nel corso della giornata, ad esempio, dai venditori pro o anti di servizi Web XML a MSFT).

Fare la codifica personalizzata e semplicemente estendere sia la logica per la ricerca più efficiente o scavare nella fonte parser. E 'banale scrivere la lavorazione con utensili circa codifica la sostituzione efficiente, mentre la schermatura degli agenti software e gli utenti da esso .. si vuole fare per questo in modo è facilmente migrato preservando la compatibilità e reversibilità. Inoltre, andare per la dimensione fissa vincoli / attributo-nome-traduzione.

[Si consideri fortunato con Expat :) e la sua velocità crudo. Immaginate come sviluppatori CLR amano strutture di scala XML, che abitualmente inviano 200MB sul filo nel processo di 'basta interrogare il database' ..]

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top