直接使用Saxon使用系统函数API

Using system functions directly using the Saxon API

我想使用 Saxon API 将用户提供的 JSON 文档转换为它的 XML 表示形式,之后用作 XSLT t[=31= 的输入]信息。

有没有一种方法可以在不实际使用 XQuery/XPath 的情况下进行这种转换?

我曾尝试使用 JsonToXMLFn 来模仿 json-to-xml XPath 函数而不实际编写 XSLT 或 XQuery,但我很快 运行 遇到了问题,因为它(非常合乎逻辑地)需要一个XPathContext,我没有找到使用 public API.

生成它的简单方法

目前我在用

XQueryExecutable exec = processor.newXQueryCompiler().compile("json-to-xml(.)");
XQueryEvaluator eval = exec.load();
eval.setContextItem(new XdmAtomicValue(jsonString));
XdmDestination destination = new XdmDestination();
eval.run(destination);
return destination.getXdmNode();

效果很好。但是不知道有没有不需要解析编译XQuery表达式的方法

也许 XdmFunctionItem.getSystemFunction(processor, new QName("http://www.w3.org/2005/xpath-functions", "json-to-xml"), 1).call(processor, new XdmAtomicValue(jsonString)) 可以工作,但对于 HE 10.2,它会抛出异常“动态函数需要 Saxon-PE 或更高版本”。

鉴于在 XPath 表达式中 HE 10 允许动态函数调用,我不确定这是否仍然是有意的;文档 https://saxonica.plan.io/projects/saxon/repository/he/revisions/master/entry/latest10/hej/net/sf/saxon/s9api/XdmFunctionItem.java#L69 说:

 * Get a system function. This can be any function defined in XPath 3.1 functions and operators,
 * including functions in the math, map, and array namespaces. It can also be a Saxon extension
 * function, provided a licensed Processor is used.
 * @return the requested function, or null if there is no such function. Note that some functions
 * (those with particular context dependencies) may be unsuitable for dynamic calling.
 * @throws SaxonApiException if dynamic function calls are not permitted by this Saxon Configuration

https://saxonica.plan.io/projects/saxon/repository/he/revisions/master/entry/latest10/hej/net/sf/saxon/Configuration.java#L1505 只是抛出

/**
 * Get a system function. This can be any function defined in XPath 3.1 functions and operators,
 * including functions in the math, map, and array namespaces. It can also be a Saxon extension
 * function, provided a licensed Processor is used.
 *
 * @param name  the name of the required function
 * @param arity the arity of the required function
 * @return the requested function, or null if there is no such function. Note that some functions
 * (those with particular context dependencies) may be unsuitable for dynamic calling.
 * @throws XPathException if dynamic function calls are not permitted by this Saxon Configuration
 */
public Function getSystemFunction(StructuredQName name, int arity) throws XPathException {
    throw new XPathException("Dynamic functions require Saxon-PE or higher");
}

因此,除非您使用 PE 或 EE,否则这似乎还不是受支持的选项;使用补丁 https://saxonica.plan.io/projects/saxon/repository/he/revisions/e5cb4f89b97633000285987b48638a53c6a81b51 或在未来的 Saxon HE 10 或更高版本中它将起作用。

最近的 10.3 版本现在可以使用了:

    String jsonString = "{ \"number\" : 3.14, \"boolean\": true, \"string\": \"whatever\", \"data\" : [1, 2, 3, 4] }";
    
    XdmValue jsonXml = XdmFunctionItem.getSystemFunction(processor, new QName("http://www.w3.org/2005/xpath-functions", "json-to-xml"), 1).call(processor, new XdmAtomicValue(jsonString));
    
    System.out.println(jsonXml);

给予

<map xmlns="http://www.w3.org/2005/xpath-functions">
   <number key="number">3.14</number>
   <boolean key="boolean">true</boolean>
   <string key="string">whatever</string>
   <array key="data">
      <number>1</number>
      <number>2</number>
      <number>3</number>
      <number>4</number>
   </array>
</map>