使用libexslt库将XML转换为JSON
本文同步自(最佳显示效果请点击):https://zohead.com/archives/libexslt-xml-json/
最近在一个 C 程序中碰到需要将 XML 数据转换为 JSON 数据的问题,多番查找几种方法,觉得此程序刚好用到了 Linux 下的 libexslt XSLT 库,因此想直接通过 XSLT 将 XML 转为 JSON 数据。
网上已经有了现成的 XML 转 JSON 的 XSLT 程序:
http://code.google.com/p/xml2json-xslt/
下载下来的 xml2json.xslt 程序可以很方便的将标准的 XML 文件转换为 JavaScript 样式的 JSON 数据,但经过试用之后发现此程序还是有一些不足,例如:不支持转换 XML 属性,对数组支持不好等问题。
我对 xml2json.xslt 做了一些改进,包括将 XML 中的属性名转换为 JSON 子节点(节点名称为 @attr 这种特殊的样式),并且为需要明确转换为 JSON 数组的节点(即使该节点下面只包含一个同类的子节点)增加 ifArray 属性,如果 ifArray 属性值为 yes,则在转换为 JSON 强制生成数组。
这个是我修改过的 xml2json.xslt 文件:
https://gist.github.com/zohead/9688858
Linux 系统可以方便的使用 xsltproc 命令将 XML 转换为 JSON,运行下面的命令就会直接将转换出来的 JSON 数据打印到标准输出中:
xsltproc xml2json.xslt test.xml
下面主要介绍如何在 Linux 中编程使用 libexslt 库将 XML 转换为 JSON 数据,有关 libexslt 库的介绍请参考这里:http://xmlsoft.org/libxslt/EXSLT/,可惜 libexslt 并没有详细的介绍文档,连网上的例子都很少。
这个是我的 xslt.c 实例程序:
#include <string.h> #include <libxml/xmlmemory.h> #include <libxml/debugXML.h> #include <libxml/HTMLtree.h> #include <libxml/xmlIO.h> #include <libxml/xinclude.h> #include <libxml/catalog.h> #include <libxml/parser.h> #include <libxml/parserInternals.h> #include <libxml/uri.h> #include <libxslt/xslt.h> #include <libxslt/xsltInternals.h> #include <libxslt/transform.h> #include <libxslt/xsltutils.h> #include <libexslt/exslt.h> #include <libexslt/exsltconfig.h> #include <libexslt/exsltexports.h> int xslProc(const char *xslfile, const char *xmlfile, const char *outfile, const char *xmlstr, char *lpbuf, size_t bufsize) { xsltStylesheetPtr cur = NULL; xmlDocPtr doc = NULL, res = NULL; int iRet = -1; if (xslfile == NULL || !xslfile[0] || ((xmlfile == NULL || !xmlfile[0]) && (xmlstr == NULL || !xmlstr[0])) || ((outfile == NULL || !outfile[0]) && lpbuf == NULL)) return -1; exsltRegisterAll(); xmlInitParser(); xmlSubstituteEntitiesDefault(1); xmlLoadExtDtdDefaultValue = 1; cur = xsltParseStylesheetFile((const xmlChar *)xslfile); if (cur) { if (xmlfile) doc = xmlParseFile(xmlfile); else doc = xmlParseMemory(xmlstr, strlen(xmlstr)); if (doc) { res = xsltApplyStylesheet(cur, doc, NULL); if (res) { if (outfile) iRet = xsltSaveResultToFilename(outfile, res, cur, 0); else { char *out = NULL; int outlen = 0; iRet = xsltSaveResultToString((xmlChar **)&out, &outlen, res, cur); if (out) { if (iRet == 0) strncpy(lpbuf, out, bufsize); free(out); } } xmlFreeDoc(res); } else iRet = 1; xmlFreeDoc(doc); } else iRet = 2; xsltFreeStylesheet(cur); } else iRet = 3; xsltCleanupGlobals(); xmlCleanupParser(); return iRet; }
程序传入 XSLT 文件名,支持 XML 字符串、XML 文件以及输出到文件及保存到字符串的方式。
具体实现方法还是比较简单的,使用 Linux 的 libexslt 库解析 XSLT 文件(xsltParseStylesheetFile),libxml 库来解析 XML 文件(xmlParseFile 和 xmlParseMemory 函数),使用 libexslt 库应用 XSLT stylesheet(xsltApplyStylesheet),保存结果数据使用 xsltSaveResultToFilename 和 xsltSaveResultToString 函数,程序中需要特别注意的就是 libxml 和 libexslt 库中众多的初始化和释放操作。