我如何使用Saxon以有效的方式对值进行多次搜索/替换

时间:2015-07-21 21:08:07

标签: xml xslt saxon

我使用saxon v9来分析将XML转换为JSON的XSL转换。分析器告诉我,逃避某些字符的函数占用总处理时间的大约70%。转换很重要,否则创建的JSON文件将因为破坏字符串的字符而无效。

java -jar saxon9he.jar -xsl:jsontransform.xslt -s:input.xml -o:output.json -TP

"方法"用于转义值如下所示:

<xsl:template name="escapejson">
        <xsl:param name="string"/>
        <xsl:sequence select="replace(
                              replace(
                              replace(
                              replace(
                              replace( 
                              replace(
                              replace(
                              replace(
                              replace($string, '\\','\\\\'), 
                              '/', '\\/'),
                              '&quot;', '\\&quot;'),
                              '&#xA;','\\n'),
                              '&#xD;','\\r'),      
                              '&#x9;','\\t'),  
                              '\n','\\n'),
                              '\r','\\r'),
                              '\t','\\t')"/>
    </xsl:template>

我已经收到了来自this other post的Rolf Lear @rolfl的宝贵建议,并减少了替换电话的数量:

...
replace( '\n|&#xA;','\\n'),
replace( '\r|&#xD;','\\r'),      
replace( '\t|&#x9;','\\t')
...

但遗憾的是,它无法在我的时间限制内处理数据。我将xsl的原始形式与修改过的形式进行了比较,花费的时间几乎相等。

因为XSL在软件设备上运行,所以我没有文件级访问权限,我需要一个saxon 8的解决方案,因为这是应该在那里使用的版本。我认为将Java集成到xsl不是一个选项,因为(但我还没有测试过),出于安全原因,设备会阻止这种情况。

1 个答案:

答案 0 :(得分:7)

您要替换的所有字符串都是单个字符,您可以利用这一事实。我想大多数字符串可能不包含这些特殊字符。因此,最好的方法可能是在更换之前对字符串进行初始检查,看它是否包含任何这些字符。这可以使用translate有效地完成:如果以下表达式为真

$x eq translate($x, '\/"&#xa;....', '')

然后不需要替换。幸运的是,这会将要处理的字符串数量减少到总数的一小部分,因此多次替换的效率不再重要。

另一种方法是将替换逻辑重新编码为:

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),
  "")

顺便说一句,我认为replace(X, '\n', Y)replace(X, '&#xa;', Y)完全相同,因此两者都是多余的。

你说你需要使用Saxon 8.实际上有一系列从Saxon 8.0到Saxon 8.9的发布,它们之间有大量的发展。我不打算查看记录,以便了解在何时推出了哪些功能。