c++ xml xpath tinyxml

c++ - ¿Debo usar XPath o simplemente DOM?



xml tinyxml (4)

En general, prefiero las soluciones basadas en XPath por su concisión y versatilidad pero, sinceramente, en su caso, no creo que usar XPath aportará mucho a su signature .

Aquí es por qué:

Código elegancia
Su código es agradable y compacto, y no mejorará con una expresión XPath.

Huella de memoria
A menos que su archivo de configuración XML de entrada sea enorme (una especie de oxímoron) y el análisis DOM implicaría una gran huella de memoria, para la cual no hay pruebas de que usar XPath sería una cura decisiva, me quedaría con DOM.

Velocidad de ejecución
En un árbol XML tan simple, la velocidad de ejecución debería ser comparable. Si hubiera una diferencia, probablemente estaría en la ventaja de TinyXml debido a la colocación de las etiquetas de level y frecuencia bajo un nodo determinado.

Bibliotecas y referencias externas Ese es el punto decisivo.
El principal motor XPath en el mundo C ++ es XQilla . Es compatible con XQuery (por lo tanto, XPath 1.0 y 2.0) y está respaldado por Oracle porque está desarrollado por el grupo responsable de los productos Berkeley DB (incluido precisamente Berkeley DB XML, que usa XQilla ).
El problema para los desarrolladores de C ++ que desean usar XQilla es que tienen varias alternativas

  1. use Xerces 2 y XQilla 2.1 litter su código con moldes.
  2. usa XQilla 2.2+ y usa Xerces 3 (no se necesitan moldes aquí)
  3. utiliza TinyXPath muy bien integrado con TinyXml, pero para el cual hay una serie de limitaciones (sin soporte para espacios de nombres, por ejemplo)
  4. mezcla Xerces y tinyXml

En resumen, en su caso cambiarse a XPath solo por el hecho de hacerlo, traería poco beneficio si alguno.

Sin embargo, XPath es una herramienta muy poderosa en la caja de herramientas de desarrolladores de hoy en día y nadie puede ignorarla. Si solo desea practicar en un ejemplo simple, el suyo es tan bueno como cualquiera. Entonces, tendría en cuenta los puntos anteriores y probablemente utilice TinyXPath de todos modos.

Tengo un montón de datos jerárquicos almacenados en un archivo XML. Lo estoy resumiendo detrás de las clases hechas a mano usando TinyXML. Dado un fragmento XML que describe una firma de origen como un conjunto de pares (frecuencia, nivel) un poco como este:

<source> <sig><freq>1000</freq><level>100</level><sig> <sig><freq>1200</freq><level>110</level><sig> </source>

Estoy extrayendo los pares con esto:

std::vector< std::pair<double, double> > signature() const { std::vector< std::pair<double, double> > sig; for (const TiXmlElement* sig_el = node()->FirstChildElement ("sig"); sig_el; sig_el = sig_el->NextSiblingElement("sig")) { const double level = boost::lexical_cast<double> (sig_el->FirstChildElement("level")->GetText()); const double freq = boost::lexical_cast<double> (sig_el->FirstChildElement("freq")->GetText()); sig.push_back (std::make_pair (freq, level)); } return sig; }

donde nodo () apunta al nodo <source> .

Pregunta: ¿podría obtener una pieza de código más ordenada, más elegante, más fácil de mantener o de alguna otra manera mejor utilizando una biblioteca XPath en su lugar?

Actualización: lo he probado usando TinyXPath de dos maneras. Ninguno de los dos trabaja, lo que obviamente es un gran punto contra ellos. ¿Estoy haciendo algo fundamentalmente malo? Si esto es lo que va a parecer con XPath, no creo que me esté consiguiendo nada.

std::vector< std::pair<double, double> > signature2() const { std::vector< std::pair<double, double> > sig; TinyXPath::xpath_processor source_proc (node(), "sig"); const unsigned n_nodes = source_proc.u_compute_xpath_node_set(); for (unsigned i = 0; i != n_nodes; ++i) { TiXmlNode* s = source_proc.XNp_get_xpath_node (i); const double level = TinyXPath::xpath_processor(s, "level/text()").d_compute_xpath(); const double freq = TinyXPath::xpath_processor(s, "freq/text()").d_compute_xpath(); sig.push_back (std::make_pair (freq, level)); } return sig; } std::vector< std::pair<double, double> > signature3() const { std::vector< std::pair<double, double> > sig; int i = 1; while (TiXmlNode* s = TinyXPath::xpath_processor (node(), ("sig[" + boost::lexical_cast<std::string>(i++) + "]/*").c_str()). XNp_get_xpath_node(0)) { const double level = TinyXPath::xpath_processor(s, "level/text()").d_compute_xpath(); const double freq = TinyXPath::xpath_processor(s, "freq/text()").d_compute_xpath(); sig.push_back (std::make_pair (freq, level)); } return sig; }

Como problema secundario, si es así, ¿qué biblioteca XPath debería usar?


Necesita XPath si necesita flexibilidad para realizar cambios en el tiempo de ejecución a los valores extraídos.

Pero, si es poco probable que necesite este tipo de flexibilidad, o una recompilación para expandir lo que está extrayendo no es un problema y las cosas no se cambian a menudo o si los usuarios no necesitan actualizar las expresiones. O si lo que tienes funciona bien para ti, no necesitas XPath y hay muchas aplicaciones que no lo usan.

En cuanto a si es más legible, bueno, sí, puede ser. Pero si solo está sacando algunos valores, cuestionaría la necesidad de incorporar otra biblioteca.

Definitivamente documentaré lo que actualmente tiene un poco mejor, ya que aquellos que no están familiarizados con las bibliotecas tinyxml o xml pueden no estar seguros de lo que está haciendo, pero no es difícil de entender como es.

No estoy seguro de qué tipo de XPath general agrega, pero sospecho que puede agregar algo. Para la mayoría, supongo que no notarán ninguna diferencia y es posible que no le preocupe a usted ni a la mayoría de las personas, pero tenga en cuenta que es algo que le preocupa.

Si desea utilizar una biblioteca xpath, todo lo que puedo decir es que he usado la que viene con Xerces-C ++ y que no fue demasiado difícil de aprender. He usado TinyXML antes y alguien aquí ha mencionado TinyXPath . No tengo experiencia con eso, pero está disponible.

También encontré este enlace útil cuando aprendí por primera vez sobre expresiones XPath. http://www.w3schools.com/xpath/default.asp


XPath está hecho para esto, por lo que, por supuesto, su código será "mejor" si lo usa.

No puedo recomendar una biblioteca específica XPath de c ++, pero aunque usar una será la decisión correcta la mayor parte del tiempo, realice un análisis de costo / beneficio antes de agregar una. Quizás YAGNI .


Esta expresión XPath :

/*/sig[$pN]/*

selecciona todos los elementos secundarios (solo el par de freq y level ) del elemento $ pN-th sig del elemento superior del documento XML.

La cadena $pN debe sustituir por un entero positivo específico , por ejemplo:

/*/sig[2]/*

selecciona estos dos elementos :

<freq>1200</freq><level>110</level>

Usar una expresión XPath ya que esto es obviamente mucho más corto y comprensible que el código proporcionado de C ++.

Otra ventaja es que la misma expresión XPath se puede usar desde un programa C # o Java o ..., sin tener que modificarlo de ninguna manera, por lo que adherir a los resultados de XPath en un alto grado de portabilidad.