Assim como nos contêineres de biblioteca padrão, qual biblioteca você deve usar depende de suas necessidades. Aqui está um fluxograma conveniente:
Portanto, a primeira pergunta é a seguinte: O que você precisa?
Preciso de total conformidade com XML
OK, então você precisa processar o XML. Não brinquedo XML, XML real . Você precisa ler e gravar toda a especificação XML, não apenas os bits mais baixos e fáceis de analisar. Você precisa de Namespaces, DocTypes, substituição de entidade, os trabalhos. A especificação XML do W3C, na sua totalidade.
A próxima pergunta é: sua API precisa estar em conformidade com DOM ou SAX?
Preciso de conformidade exata com DOM e / ou SAX
OK, então você realmente precisa que a API seja DOM e / ou SAX. Ele não pode ser apenas um analisador push no estilo SAX ou um analisador retido no estilo DOM. Ele deve ser o DOM real ou o SAX real, na extensão permitida pelo C ++.
Você escolheu:
Xerces
Essa é sua escolha. É praticamente o único analisador / gravador XML de C ++ que possui total (ou o mais próximo que o C ++ permite) conformidade com DOM e SAX. Ele também possui suporte ao XInclude, suporte ao esquema XML e uma infinidade de outros recursos.
Não possui dependências reais. Ele usa a licença Apache.
Não ligo para a conformidade com DOM e / ou SAX
Você escolheu:
LibXML2
O LibXML2 oferece uma interface no estilo C (se isso realmente o incomoda, vá usar o Xerces), embora a interface seja pelo menos um pouco baseada em objetos e facilmente envolvida. Ele fornece muitos recursos, como suporte ao XInclude (com retornos de chamada para que você possa saber de onde o arquivo é obtido), um reconhecedor XPath 1.0, suporte para RelaxNG e Schematron (embora as mensagens de erro deixem muito a desejar) e assim por diante.
Ele depende do iconv, mas pode ser configurado sem essa dependência. Embora isso signifique que você terá um conjunto mais limitado de possíveis codificações de texto que ele pode analisar.
Ele usa a licença do MIT.
Não preciso de conformidade total com XML
OK, então a total conformidade com XML não importa para você. Seus documentos XML estão totalmente sob seu controle ou são garantidos para usar o "subconjunto básico" do XML: sem espaços para nome, entidades, etc.
Então, o que importa para você? A próxima pergunta é: Qual é a coisa mais importante para você no seu trabalho XML?
Desempenho máximo de análise de XML
Seu aplicativo precisa pegar o XML e transformá-lo em estruturas de dados C ++ o mais rápido possível.
Você escolheu:
RapidXML
Esse analisador XML é exatamente o que diz no estanho: XML rápido. Nem sequer trata de puxar o arquivo para a memória; como isso acontece depende de você. O que ele lida é analisar isso em uma série de estruturas de dados C ++ que você pode acessar. E faz isso o mais rápido possível para verificar o arquivo byte a byte.
Claro, não existe almoço grátis. Como a maioria dos analisadores XML que não se importam com a especificação XML, o Rapid XML não toca em espaços para nome, DocTypes, entidades (com exceção das entidades de caractere e das 6 XML básicas) e assim por diante. Então, basicamente nós, elementos, atributos e outros.
Além disso, é um analisador no estilo DOM. Portanto, é necessário que você leia todo o texto. No entanto, o que ele não faz é copiar esse texto (geralmente). A maneira como o RapidXML obtém a maior parte de sua velocidade é consultando as strings no local . Isso requer mais gerenciamento de memória de sua parte (você deve manter essa string ativa enquanto o RapidXML estiver olhando para ela).
O DOM do RapidXML é básico. Você pode obter valores de sequência para as coisas. Você pode procurar atributos por nome. É sobre isso. Não há funções de conveniência para transformar atributos em outros valores (números, datas, etc.). Você acabou de pegar as cordas.
Outra desvantagem do RapidXML é que é doloroso escrever XML. Exige que você faça muita alocação de memória explícita dos nomes de cadeias para criar seu DOM. Ele fornece um tipo de buffer de cadeia, mas isso ainda exige muito trabalho explícito do seu lado. Certamente é funcional, mas é difícil de usar.
Ele usa a licença do MIT. É uma biblioteca somente de cabeçalho sem dependências.
Eu me importo com o desempenho, mas não tanto assim
Sim, o desempenho é importante para você. Mas talvez você precise de algo um pouco menos básico. Talvez algo que possa lidar com mais Unicode ou não exija muito gerenciamento de memória controlado pelo usuário. O desempenho ainda é importante, mas você deseja algo um pouco menos direto.
Você escolheu:
PugiXML
Historicamente, isso serviu de inspiração para o RapidXML. Mas os dois projetos divergiram, com o Pugi oferecendo mais recursos, enquanto o RapidXML está totalmente focado na velocidade.
O PugiXML oferece suporte à conversão Unicode; portanto, se você possui alguns documentos UTF-16 e deseja lê-los como UTF-8, o Pugi fornecerá. Ele ainda tem uma implementação XPath 1.0, se você precisar desse tipo de coisa.
Mas Pugi ainda é bastante rápido. Como o RapidXML, ele não possui dependências e é distribuído sob a licença MIT.
Lendo documentos enormes
Você precisa ler documentos que são medidos em gigabytes de tamanho. Talvez você os esteja recebendo do stdin, sendo alimentado por outro processo. Ou você está lendo-os de arquivos enormes. Como queiras. O ponto é que você precisa não ter que ler o arquivo inteiro na memória de uma só vez para processá-lo.
Você escolheu:
LibXML2
A API no estilo SAX do Xerces funcionará nessa capacidade, mas o LibXML2 está aqui porque é um pouco mais fácil de trabalhar. Uma API no estilo SAX é uma API push: ela começa a analisar um fluxo e apenas dispara os eventos que você precisa capturar. Você é forçado a gerenciar contexto, estado e assim por diante. O código que lê uma API no estilo SAX é muito mais espalhado do que se poderia esperar.
O xmlReader
objeto do LibXML2 é uma API pull. Você pede para ir para o próximo nó ou elemento XML; você não é informado. Isso permite que você armazene o contexto como achar melhor, para lidar com diferentes entidades de uma maneira muito mais legível no código do que um monte de retornos de chamada.
Alternativas
Expatriados
Expat é um analisador C ++ conhecido que usa uma API pull-parser. Foi escrito por James Clark.
Seu status atual está ativo. A versão mais recente é 2.2.9, que foi lançada em (2019-09-25).
LlamaXML
É uma implementação de uma API no estilo StAX. É um analisador de pull, semelhante ao xmlReader
analisador do LibXML2 .
Mas não é atualizado desde 2005. Mais uma vez, Caveat Emptor.
Suporte XPath
XPath é um sistema para consultar elementos dentro de uma árvore XML. É uma maneira prática de nomear efetivamente um elemento ou coleção de elementos por propriedades comuns, usando uma sintaxe padronizada. Muitas bibliotecas XML oferecem suporte ao XPath.
Existem efetivamente três opções aqui:
- LibXML2 : Fornece suporte completo ao XPath 1.0. Novamente, é uma API C, portanto, se isso lhe incomoda, existem alternativas.
- PugiXML : Ele também vem com o suporte ao XPath 1.0. Como acima, é mais uma API C ++ que LibXML2, então você pode se sentir mais confortável com ela.
- TinyXML : Ele não vem com suporte para XPath, mas existe a biblioteca TinyXPath que o fornece. O TinyXML está passando por uma conversão para a versão 2.0, que altera significativamente a API, portanto, o TinyXPath pode não funcionar com a nova API. Como o próprio TinyXML, o TinyXPath é distribuído sob a licença zLib.
Apenas comece o trabalho
Portanto, você não se importa com a correção de XML. O desempenho não é um problema para você. Streaming é irrelevante. Tudo o que você deseja é algo que coloque XML na memória e permita que você o cole novamente no disco. O que você importa é API.
Você deseja um analisador XML que seja pequeno, fácil de instalar, trivial de usar e pequeno o suficiente para ser irrelevante para o tamanho do seu eventual executável.
Você escolheu:
TinyXML
Coloquei o TinyXML neste slot porque é tão simples de usar quanto os analisadores XML. Sim, é lento, mas é simples e óbvio. Possui muitas funções de conveniência para converter atributos e assim por diante.
Escrever XML não é problema no TinyXML. Você apenas new
coloca alguns objetos, os anexa, envia o documento para a std::ostream
e todos ficam felizes.
Também existe um ecossistema construído em torno do TinyXML, com uma API mais amigável ao iterador e até mesmo uma implementação XPath 1.0 em camadas.
O TinyXML usa a licença zLib, que é mais ou menos a Licença MIT com um nome diferente.