使用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 库中众多的初始化和释放操作。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*