Pergunta

Aplicação de Nossa C ++ lê dados de configuração de arquivos XML que algo parecido com isto:

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

A configuração da aplicação completa consistem em ~ 2.500 desses arquivos XML (que se traduz em mais de 1,5 milhões de pares atributo-chave / valor). Os arquivos XML vêm de muitas diferentes fontes / equipes e são validados contra um esquema. No entanto, às vezes os nós <value/> parecido com este:

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

ou este:

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

Para tornar esse processo rápido, estamos usando Expat para analisar os documentos XML. Expat expõe os atributos como uma matriz - como esta:

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

Tudo isso coloca a responsabilidade para nossa função ProcessAttribute() para ler a 'chave' e decidir o que fazer com o valor. perfilar o aplicativo mostrou que ~ 40% do XML tempo total de análise é lidar com esses atributos por nome / string.

O processo global poderia ser acelerado dramaticamente se eu poderia garantir / impor a ordem dos atributos (para iniciantes, há comparações de strings em ProcessAttribute()). Por exemplo, se o atributo 'id' era sempre 1º atributo poderíamos lidar com isso diretamente:

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 acordo com as especificações de esquema W3C, posso usar <xs:sequence> em um esquema XML para impor a ordem dos elementos - mas não parece trabalho para atributos - ou talvez eu estou usando-o incorretamente:

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

Existe uma maneira de impor ordem atributo em um documento XML? Se a resposta for "não"? - alguém poderia talvez sugerir uma alternativa que não iria realizar uma grande penalidade de desempenho de tempo de execução

Foi útil?

Solução

De acordo com a especificação XML,

a fim de especificações de atributos em uma marca de início ou de elemento vazio não é significativa

Você pode verificá-la em secção 3.1

Outras dicas

atributos XML não Have uma ordem, portanto, não há nenhuma ordem para fazer cumprir.

Se você quiser algo ordenado, você precisa de elementos XML. Ou algo diferente do XML. JSON, YAML e bEncode, v.g. têm ambos os mapas (que são não-ordenada) e sequências (que são ordenados).

Como outros apontaram, não, você não pode confiar na ordenação atributo.

Se eu tivesse qualquer processo em tudo que envolve 2.500 arquivos XML e pares de 1,5 milhões de chave / valor, gostaria de obter esses dados para fora do XML e em uma forma mais utilizável, logo que eu podia. Um banco de dados, um formato de serialização binária, seja qual for. Você não está recebendo qualquer vantagem fora de usar XML (que não validação do esquema). Eu atualizar minha loja cada vez que eu tenho um novo arquivo XML, e tomar a análise de 1,5 milhões de elementos XML para fora do fluxo principal do meu processo.

A resposta é não, infelizmente. Estou chocado com a sua figura de 40%. Acho que é difícil acreditar que transformar "foo" em ProcessFoo leva muito tempo. Tem certeza que o 40% não inclui o tempo necessário para executar ProcessFoo?

É possível acessar os atributos pelo nome usando essa coisa Expat? Essa é a forma mais tradicional de atributos de acesso. Eu não estou dizendo que vai ser mais rápido, mas pode valer a pena uma tentativa.

Eu não acho que XML Schema apoios que - atributos são apenas definida e restrita pelo nome, por exemplo, eles têm que corresponder a um nome particular - mas eu não vejo como você pode definir uma ordem para esses atributos em XSD

.

Eu não sei de nenhuma outra maneira de certificar-se de atributos em um nó XML vêm em uma ordem específica - não tenho certeza se qualquer um dos outros mecanismos de esquema XML como Schematron ou Relax NG apoiaria que ....

Eu tenho certeza que não há nenhuma maneira de impor ordem atributo em um documento XML. Eu estou indo supor que você pode insistir em que através de um processo de negócio ou outros fatores humanos, como um contrato ou outro documento.

E se você só assumiu que o primeiro atributo foi "id", e testou o nome para ter certeza? Se sim, use o valor, se não, então você pode tentar obter o atributo por nome ou jogar fora o documento.

Apesar de não ser tão eficiente quanto chamando o atributo pelo seu ordinal, um número diferente de zero de vezes que você vai ser capaz de adivinhar que seus provedores de dados ter entregue XML para spec. O resto do tempo, você pode tomar outras medidas.

Apenas um palpite, mas você pode tentar adicionar use="required" para cada uma de suas especificações de 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>

Eu estou querendo saber se o analisador está sendo retardado por permitindo atributos opcionais, quando ela aparece seus atributos sempre estará lá.

Mais uma vez, apenas uma suposição.

EDIT: XML 1.0 especificação diz que a ordem atributo não é significativo. http://www.w3.org/TR/REC-xml/# sec-starttags

Portanto, XSD não impor qualquer ordem. Mas isso não significa que os analisadores não pode ser enganado em trabalhar rapidamente, assim que eu estou mantendo a resposta acima publicada em caso ele realmente funciona.

Pelo que me lembro, Expat é um analisador não validar e melhor para ele .. assim você pode provavelmente sucata a idéia XSD. Nem é a idéia de um bom dependentes fim-in muitos XML aproxima (XSD foi criticado na ordem dos elementos de um pedaço de uma volta muito em dia, por exemplo, por vendedores pró ou anti de XML Web Services no MSFT).

Faça a sua codificação personalizado e simplesmente estender tanto a sua lógica para pesquisa mais eficiente ou cavar a fonte analisador. É trivial para escrever o ferramental em torno de codificação de substituição eficiente, enquanto protegendo os agentes de software e usuários a partir dele .. você quer fazer a esta por isso é facilmente migrado, preservando a compatibilidade e reversibilidade. Além disso, ir para a restrições de tamanho fixo / atributo-name-tradução.

[considere-se afortunado com Expat :) e sua velocidade crua. Imagine como CLR devs instalações de escala amor XML, eles rotineiramente enviar 200MB no fio em processo de 'apenas consultando o banco de dados' ..]

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top