Используйте внешние переменные в саксонской - PullRequest
0 голосов
/ 19 февраля 2019

У меня есть XQuery, который конвертирует Json в Json.Я сделал демо-версию, которая работает в командной строке, и я хочу использовать ее в Java.

Проблема в том, что я не знаю, как установить параметры в XQuery.

Мойисходный файл "1.json":

{
 "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, который я хочу использовать "XQuery.xq":

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 -cp saxon9he.jar net.sf.saxon.Query -t -q:test\Query.xq >test\Test.json

В Java я написал следующее (не работает! => Я получаю SXXP0003: Ошибка, сообщаемая анализатором XML: содержимое не разрешено в прологе.):

    @Test
public void test_XQuery() throws Exception {
    runXQuery("/1.json", "/XQuery.xq", "/1_Output.json");
}

private void runXQuery(String datafile, String xQueryFile, String expectedOutput) throws Exception {
    InputStream dataStream = getClass().getResourceAsStream(datafile);
    InputStream xQueryStream = getClass().getResourceAsStream(xQueryFile);

    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    run(dataStream, xQueryStream, outputStream);
    String json = outputStream.toString();

    String expected = StreamUtils.copyToString(getClass().getResourceAsStream(expectedOutput), Charset.defaultCharset());
    assertEquals(expected, json);
}

private static void run(InputStream input, InputStream query, OutputStream output) throws SaxonApiException {
    Configuration config = Configuration.newConfiguration();
    Processor processor = new Processor(config);
    XQueryCompiler compiler = processor.newXQueryCompiler();
    XQueryExecutable executor = compiler.compile(query);
    XQueryEvaluator evaluator = executor.load();

    Source sourceInput = new SAXSource(new InputSource(input));
    DocumentBuilder builder = processor.newDocumentBuilder();
    XdmNode doc = builder.build(sourceInput);
    evaluator.setContextItem(doc);

//    QName qName = new QName("input");
//    evaluator.setExternalVariable(qName, doc);

    Serializer out = processor.newSerializer(output);
    out.setOutputProperty(Serializer.Property.METHOD, "json");

    evaluator.run(out);
}

Мой вопрос: Как мне изменитьмой "XQuery.xq" и мой код Java, чтобы я мог использовать несколько входных файлов.например, "2.json", ...

1 Ответ

0 голосов
/ 19 февраля 2019

Ну, во-первых, в этом запросе нет никаких внешних переменных, что делает заголовок вопроса довольно запутанным.Внешняя переменная будет объявлена ​​так:

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.Вы можете установить базовый URI для запроса, используя XQueryCompiler.setBaseURI (), или вы можете разрешить имя файла в своем коде Java и предоставить абсолютный URI для ввода JSON.

...