在Saxon中使用外部变量

时间:2019-02-19 13:54:29

标签: java xquery saxon

我有一个将Json转换为Json的XQuery。 我制作了一个可以在命令行上运行的演示版本,我想在Java中使用它。

问题是我不知道如何在XQuery中设置参数。

我的源文件“ 1.json”:

for block in result:
    description = {}
    for dic in block:
        if dic.__contains__('descr'):
            description = {i:j for i in dic.keys() for j in zip(dic.values(),description.values())}
    block.append(description)

我要使用“ XQuery.xq”的XQuery:

{
 "FirstName": "Fred",
 "Surname": "Smith",
 "Age": 28,
 "Phone": [{
   "type": "home",
   "number": "0203 544 1234"
  }, {
   "type": "office",
   "number": "01962 001234"
  }, {
   "type": "office",
   "number": "01962 001235"
  }, {
   "type": "mobile",
   "number": "077 7700 1234"
  }
 ]
}

命令行:

xquery version "3.1";
declare namespace array = "http://www.w3.org/2005/xpath-functions/array";
declare namespace map = "http://www.w3.org/2005/xpath-functions/map";
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare option output:method "json";

let $j := json-doc( 'src/test/resources/1.json' )
where ("Fred" = $j?FirstName or 30 != $j?Age) (:predicate on the highest level:)
return array {
  for $i in (1 to $j?Phone => array:size()) (:predicate on the next level:)
  let $e := $j?Phone($i)
  where ($e?type = "home" or fn:matches($e?type, "^mob.*$")) (:implementing like using regular expressions % => .*, ? => . , ^/$ Start/End of line  :)
  return map {
    "Name (First)": data($j?FirstName),
    "Name (Last)": data($j?Surname),
    "age": data($j?Age),
    "Phone": data($e?number),
    "ConstantValue": "TEST"
  }
}

在Java中,我编写了以下内容(不起作用!=>我得到了SXXP0003:XML解析器报告的错误:序言中不允许内容。)

java -cp saxon9he.jar net.sf.saxon.Query -t -q:test\Query.xq >test\Test.json

我的问题:如何更改“ XQuery.xq”和Java代码,以便可以使用多个输入文件。例如“ 2.json”,...

1 个答案:

答案 0 :(得分:2)

首先,此查询中没有任何外部变量,这使得问题标题相当混乱。可以这样声明一个外部变量:

declare variable $param as xs:string external;

您得到的错误是因为您正在提供一个JSON文件作为SAXSource的输入。 SAX用于读取XML文件,而XML解析器(SXXP0003)出现错误是因为XML解析器无法读取JSON文件。

如果您想使用要读取的JSON文件的文件名对查询进行参数化,我会这样做:

declare variable $jsonFile as xs:string external;
let $j := json-doc($jsonFile)...

,然后使用提供文件名

QName qName = new QName("jsonFile");
evaluator.setExternalVariable(qName, "src/test/resources/1.json");

唯一剩下的问题是有关相对文件名的解析。我在这里所做的方式,文件名“ src / test / resources ...”将被解释为相对于查询的位置(静态基本URI),在您的情况下是未知的,因为您正在提供以匿名InputStream查询。您可以使用XQueryCompiler.setBaseURI()为查询设置基本URI,或者可以解析Java代码中的文件名并为JSON输入提供绝对URI。