我使用saxon v9来分析将XML转换为JSON的XSL转换.分析器告诉我,逃避某些字符的函数占用总处理时间的大约70%.转换很重要,否则创建的JSON文件将因为破坏字符串的字符而无效.
java -jar saxon9he.jar -xsl:jsontransform.xslt -s:input.xml -o:output.json -TP
Run Code Online (Sandbox Code Playgroud)
用于转义值的"方法"如下所示:
<xsl:template name="escapejson">
<xsl:param name="string"/>
<xsl:sequence select="replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace($string, '\\','\\\\'),
'/', '\\/'),
'"', '\\"'),
'
','\\n'),
'
','\\r'),
'	','\\t'),
'\n','\\n'),
'\r','\\r'),
'\t','\\t')"/>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)
我已经收到Rolf Lear @rolfl在这篇文章中提出的宝贵建议,并减少了替换电话的数量:
...
replace( '\n|
','\\n'),
replace( '\r|
','\\r'),
replace( '\t|	','\\t')
...
Run Code Online (Sandbox Code Playgroud)
但不幸的是,它无法在我的时间限制内处理数据.我将xsl的原始形式与修改过的形式进行了比较,花费的时间几乎相等.
因为XSL在软件设备上运行,所以我没有文件级访问权限,我需要一个saxon 8的解决方案,因为这是应该在那里使用的版本.我认为将Java集成到xsl不是一个选项,因为(但我还没有测试过),出于安全原因,设备会阻止这种情况.
您要替换的所有字符串都是单个字符,您可以利用这一事实.我想大多数字符串可能不包含这些特殊字符.因此,最好的方法可能是在更换之前对字符串进行初始检查,看它是否包含任何这些字符.这可以使用translate有效地完成:如果以下表达式为真
$x eq translate($x, '\/"
....', '')
Run Code Online (Sandbox Code Playgroud)
然后不需要更换.幸运的是,这将把要完全处理的字符串数量减少到总数的一小部分,因此多次替换的效率不再重要.
另一种方法是将替换逻辑重新编码为:
string-join(
for $c in string-to-codepoints($in)
return
if ($c eq XX) then "\\"
else if ($x eq XY) then "\n"
else if ....
else codepoints-to-string($c),
"")
Run Code Online (Sandbox Code Playgroud)
顺便说一句,我认为这replace(X, '\n', Y)意味着完全相同,replace(X, '
', Y)因此两者都是多余的.
你说你需要使用Saxon 8.实际上有一系列从Saxon 8.0到Saxon 8.9的发布,它们之间有大量的发展.我不打算查看记录,以便了解何时引入了哪些功能.