QString XSLTransformer::transform(const QString &xml, QHash<QString, QString> const ¶ms) const { // Read XML data intro an xmlDoc. QByteArray xmlData(xml.toUtf8()); QScopedPointer<xmlDoc, XmlDocDeleter> doc( xmlReadMemory(xmlData.constData(), xmlData.size(), 0, 0, 0)); if (!doc) throw std::runtime_error("XSLTransformer::transform: Could not open XML data"); // Hmpf, data conversions. char const **cParams = new char const *[params.size() * 2 + 1]; int i = 0; for (QHash<QString, QString>::const_iterator iter = params.constBegin(); iter != params.constEnd(); ++iter) { QByteArray keyData(iter.key().toUtf8()); QByteArray valueData(iter.value().toUtf8()); char const *cKey = strdup(keyData.constData()); char const *cValue = strdup(valueData.constData()); cParams[i] = cKey; cParams[i + 1] = cValue; i += 2; } cParams[params.size() * 2] = 0; // Terminator QScopedPointer<xsltTransformContext, XsltTransformContextDeleter> ctx( xsltNewTransformContext(d_xslPtr.data(), doc.data())); xsltSetCtxtParseOptions(ctx.data(), XSLT_PARSE_OPTIONS); // Transform... QScopedPointer<xmlDoc, XmlDocDeleter> res( xsltApplyStylesheetUser(d_xslPtr.data(), doc.data(), cParams, NULL, NULL, ctx.data())); if (!res) throw std::runtime_error("XSLTransformer::transform: Could not apply transformation!"); else if (ctx->state != XSLT_STATE_OK) throw std::runtime_error("XSLTransformer::transform: Transformation error, check your query!"); xmlChar *outputBare = 0; int outputLen = -1; xsltSaveResultToString(&outputBare, &outputLen, res.data(), d_xslPtr.data()); QScopedPointer<xmlChar, XmlDeleter> output(outputBare); if (!output) throw std::runtime_error("Could not apply stylesheet!"); QString result(QString::fromUtf8(reinterpret_cast<char const *>(output.data()))); // Deallocate parameter memory for (int i = 0; i < params.size() * 2; ++i) free(const_cast<char *>(cParams[i])); delete[] cParams; return result; }
/* Wrapper for xsltApplyStylesheet */ xmlDocPtr mxslt_doc_xml_apply_stylesheet(mxslt_doc_t * mxslt_doc, xsltStylesheetPtr style, xmlDocPtr doc, const char ** params) { xmlDocPtr retval; xsltTransformContextPtr userCtxt; userCtxt=xsltNewTransformContext(style, doc); if(userCtxt == NULL) return NULL; xsltSetCtxtParseOptions(userCtxt, MXSLT_XSLT_OPTIONS); /* XXX I don't like this much :| ... I consider this an hack */ /* userCtxt->_private=(void *)mxslt_doc; */ userCtxt->outputFile=mxslt_doc->localfile; #ifndef MXSLT_DISABLE_EXTENSIONS xsltRegisterExtElement(userCtxt, (xmlChar *)"header-set", (xmlChar *)MXSLT_NS_URI, mxslt_transform_header); xsltRegisterExtElement(userCtxt, (xmlChar *)"value-of", (xmlChar *)MXSLT_NS_URI, mxslt_transform_value_of); xsltRegisterExtElement(userCtxt, (xmlChar *)"header-set", (xmlChar *)MXSLT_OBSOLETE_NS_URI, mxslt_transform_header); xsltRegisterExtElement(userCtxt, (xmlChar *)"value-of", (xmlChar *)MXSLT_OBSOLETE_NS_URI, mxslt_transform_value_of); #endif retval=xsltApplyStylesheetUser(style, doc, params, NULL, NULL, userCtxt); xsltFreeTransformContext(userCtxt); return retval; }
// Processes input XML file (e.g., instance metadata) into output XML file or string (e.g., for libvirt) // using XSL-T specification file (e.g., libvirt.xsl) static int apply_xslt_stylesheet (const char * xsltStylesheetPath, const char * inputXmlPath, const char * outputXmlPath, char * outputXmlBuffer, int outputXmlBufferSize) { int err = OK; INIT(); xsltStylesheetPtr cur = xsltParseStylesheetFile ((const xmlChar *)xsltStylesheetPath); if (cur) { xmlDocPtr doc = xmlParseFile (inputXmlPath); if (doc) { xsltTransformContextPtr ctxt = xsltNewTransformContext (cur, doc); // need context to get result xsltSetCtxtParseOptions (ctxt, 0); // TODO: do we want any XSL-T parsing options? xmlDocPtr res = xsltApplyStylesheetUser (cur, doc, NULL, NULL, NULL, ctxt); // applies XSLT to XML int applied_ok = ctxt->state==XSLT_STATE_OK; // errors are communicated via ctxt->state xsltFreeTransformContext (ctxt); if (res && applied_ok) { // save to a file, if path was provied if (outputXmlPath!=NULL) { FILE * fp = fopen (outputXmlPath, "w"); if (fp) { int bytes = xsltSaveResultToFile (fp, res, cur); if (bytes==-1) { logprintfl (EUCAERROR, "ERROR: failed to save XML document to %s\n", outputXmlPath); err = ERROR; } fclose (fp); } else { logprintfl (EUCAERROR, "ERROR: failed to create file %s\n", outputXmlPath); err = ERROR; } } // convert to an ASCII buffer, if such was provided if (err==OK && outputXmlBuffer!=NULL && outputXmlBufferSize > 0) { xmlChar * buf; int buf_size; if (xsltSaveResultToString (&buf, &buf_size, res, cur)==0) { // success if (buf_size < outputXmlBufferSize) { bzero (outputXmlBuffer, outputXmlBufferSize); for (int i=0, j=0; i<buf_size; i++) { char c = (char) buf [i]; if (c != '\n') // remove newlines outputXmlBuffer [j++] = c; } } else { logprintfl (EUCAERROR, "ERROR: XML string buffer is too small (%d > %d)\n", buf_size, outputXmlBufferSize); err = ERROR; } xmlFree (buf); } else { logprintfl (EUCAERROR, "ERROR: failed to save XML document to a string\n"); err = ERROR; } } } else { logprintfl (EUCAERROR, "ERROR: failed to apply stylesheet %s to %s\n", xsltStylesheetPath, inputXmlPath); err = ERROR; } if (res!=NULL) xmlFreeDoc(res); xmlFreeDoc(doc); } else { logprintfl (EUCAERROR, "ERROR: failed to parse XML document %s\n", inputXmlPath); err = ERROR; } xsltFreeStylesheet(cur); } else { logprintfl (EUCAERROR, "ERROR: failed to open and parse XSL-T stylesheet file %s\n", xsltStylesheetPath); err = ERROR; } return err; }