如何将 JSON 文件加载到在 Java 中运行的 Saxon 中的 DOM? [英] How do I load a JSON file into the DOM in Saxon running in Java?
问题描述
在我的 Java 代码中,我试图创建一个 Saxon 文档 (DOM),它是 JSON 文件的内容.这应该有可能,但我的代码失败了.
In my Java code I am trying to create a Saxon document (DOM) that is the contents of a JSON file. This should be possible but the code I have fails.
完整代码位于 SaxonQuestions.zip、TestLoadJson.java 也列在下面.在这段代码中,evaluate() 失败了.
The full code for this is at SaxonQuestions.zip, TestLoadJson.java and is also listed below. In this code the evaluate() fails.
TestLoadJson.java
TestLoadJson.java
import net.sf.saxon.Configuration;
import net.sf.saxon.s9api.*;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import javax.xml.transform.sax.SAXSource;
import java.io.*;
import java.nio.charset.Charset;
public class TestLoadJson {
public static void main(String[] args) throws Exception {
// get the file
File jsonFile = new File("files", "SouthWind.json");
Charset inputCharset = Charset.forName("UTF-8");
FileInputStream fis = new FileInputStream(jsonFile);
InputStreamReader isr = new InputStreamReader(fis, inputCharset);
BufferedReader br = new BufferedReader(isr);
String str;
StringBuilder buf = new StringBuilder();
while ((str = br.readLine()) != null)
buf.append(str).append('\n');
br.close();
isr.close();
fis.close();
// set up the compiler
Configuration config = XmlDatasource.createEnterpriseConfiguration();
Processor processor = new Processor(config);
XPathCompiler xPathCompiler = processor.newXPathCompiler();
// need an XML document
DocumentBuilder doc_builder = processor.newDocumentBuilder();
XMLReader reader = XmlDatasource.createXMLReader();
InputSource xmlSource = new InputSource(new ByteArrayInputStream("<root/>".getBytes()));
SAXSource saxSource = new SAXSource(reader, xmlSource);
XdmNode xmlRootNode = doc_builder.build(saxSource);
// give it the JSON
buf.insert(0, "parse-json(");
buf.append(")");
Object json = xPathCompiler.evaluate(buf.toString(), xmlRootNode);
System.out.println("JSON read in!!! json = " + json);
}
}
推荐答案
如果你有一个带有 JSON 的 Java String
将它作为变量传递给 XPath 并调用 parse-json变量上的代码>:
If you have a Java String
with JSON pass it in as a variable to XPath and call parse-json
on the variable:
Processor processor = new Processor(true);
String[] jsonExamples = { "1", "true", "null", "\"string\"", "[1,2,3]", "{ \"prop\" : \"value\" }" };
XPathCompiler compiler = processor.newXPathCompiler();
compiler.declareVariable(new QName("json"));
XPathExecutable executable = compiler.compile("parse-json($json)");
XPathSelector selector = executable.load();
for (String json : jsonExamples) {
selector.setVariable(new QName("json"), new XdmAtomicValue(json));
XdmValue value = selector.evaluate();
System.out.println(value);
}
如果您有一个带有 JSON 的文件,请将其文件名或一般 URI 作为变量传递给 XPath 并调用 json-doc
(https://www.w3.org/TR/xpath-functions/#func-json-doc) 在变量:
If you have a file with JSON pass its file name or in general URI as a variable to XPath and call json-doc
(https://www.w3.org/TR/xpath-functions/#func-json-doc) on the variable:
compiler = processor.newXPathCompiler();
compiler.declareVariable(new QName("json-uri"));
executable = compiler.compile("json-doc($json-uri)");
selector = executable.load();
selector.setVariable(new QName("json-uri"), new XdmAtomicValue("example1.json")); // pass in a relative (e.g. 'example.json' or 'subdir/example.json') or an absolute URI (e.g. 'file:///C:/dir/subdir/example.json' or 'http://example.com/example.json') here, not an OS specific file path
XdmValue value = selector.evaluate();
System.out.println(value);
当然,您可以将这些步骤分开并将字符串解析为 XdmValue 或将文件解析为 XdmValue,然后将其作为变量传递给另一个 XPath 计算.
Of course you can separate the steps and parse a string to an XdmValue or a file to an XdmValue and then pass it in later as a variable to another XPath evaluation.
所以让我们假设你有 employees.json
包含
So lets assume you have employees.json
containing
{
"employees": [
{
"name": "mike",
"department": "accounting",
"age": 34
},
{
"name": "sally",
"department": "sales",
"age": 24
}
]
}
然后您可以使用第二个样本将其解析为 XdmValue 值,并将其进一步用作表达式的上下文项,例如
then you can parse it with the second sample into an XdmValue value and use that further as a context item for an expression e.g
avg(?employees?*?age)
将计算平均年龄:
Processor processor = new Processor(true);
XPathCompiler compiler = processor.newXPathCompiler();
compiler.declareVariable(new QName("json-uri"));
XPathExecutable executable = compiler.compile("json-doc($json-uri)");
XPathSelector selector = executable.load();
selector.setVariable(new QName("json-uri"), new XdmAtomicValue("employees.json"));
XdmValue value = selector.evaluate();
System.out.println(value);
executable = compiler.compile("avg(?employees?*?age)");
selector = executable.load();
selector.setContextItem((XdmItem) value);
XdmItem result = selector.evaluateSingle();
System.out.println(result);
在 https://xqueryfiddle.liberty-development.net/94hwphZ 我有另一个示例处理 JSON,它还使用查找运算符 ?
计算带有表达式的值的平均值,首先使用 ?Students
选择 Students
上下文映射的项,然后在返回的数组上加上星号 ?*
以获得所有数组项的序列,最后用 ?Grade
选择 Grade
每个数组项的值:
At https://xqueryfiddle.liberty-development.net/94hwphZ I have another sample processing JSON, it also computes the average of a value with an expression using the lookup operator ?
, first with ?Students
to select the Students
item of the context map, then with an asterisk ?*
on the returned array to get a sequence of all array items, finally with ?Grade
to select the Grade
value of each array item:
avg(?Students?*!(?Grade, 70)[1])
但附加要求为那些没有 Grade
的对象/地图选择默认值 70
.示例 JSON 是
but with the additional requirement to select a default of 70
for those objects/maps that don't have a Grade
. The sample JSON is
{
"Class Name": "Science",
"Teacher\u0027s Name": "Jane",
"Semester": "2019-01-01",
"Students": [
{
"Name": "John",
"Grade": 94.3
},
{
"Name": "James",
"Grade": 81.0
},
{
"Name": "Julia",
"Grade": 91.9
},
{
"Name": "Jessica",
"Grade": 72.4
},
{
"Name": "Johnathan"
}
],
"Final": true
}
小提琴支持 XQuery 3.1,但与 XPath 3.1 一样,JSON 作为变量传入,然后使用 parse-json
解析为 XDM 项,作为进一步评估的上下文项.
The fiddle supports XQuery 3.1 but like for XPath 3.1 the JSON is passed in as a variable and then parsed with parse-json
into an XDM item to serve as the context item for further evaluation.
为了给出一些针对 JSON 的更复杂的 XPath 3.1 表达式的示例,我从 https://github.com/json-path/JsonPath 作为 parse-json
的 JSON 输入(如果您有字符串)或 json-doc代码> 如果您有文件的 URI 甚至 HTTP(S) 位置并将其用作某些路径的上下文项(在小提琴中评估为 XQuery 3.1 但 XPath 3.1 是一个子集,我想我已经限制了示例到 XPath 3.1:
To give some examples of more complex XPath 3.1 expressions against JSON I have taken the JSON sample from the path examples in https://github.com/json-path/JsonPath as the JSON input to parse-json
(if you have a string) or json-doc
if you have a URI to a file or even a HTTP(S) location and used it as the context item for some paths (evaluated in the fiddle as XQuery 3.1 but XPath 3.1 is a subset and I think I have restricted the samples to XPath 3.1:
样品位于:
- https://xqueryfiddle.liberty-development.net/gWmuPs6/0:
?store?book?*?author
: 所有书籍的作者" - https://xqueryfiddle.liberty-development.net/gWmuPs6/1:
?store?*
:商店里的所有东西,包括书籍和自行车" - https://xqueryfiddle.liberty-development.net/gWmuPs6/2:
?store?book?3
: 第三本书" - https://xqueryfiddle.liberty-development.net/gWmuPs6/3:
?store?book?(1,2)
: 前两本书" - https://xqueryfiddle.liberty-development.net/gWmuPs6/4:
?store?book?*[?isbn]
: 所有有 isbn 编号的书" - https://xqueryfiddle.liberty-development.net/gWmuPs6/5:
?store?book?*[?price <10]
:所有价格低于 10 的书籍" - https://xqueryfiddle.liberty-development.net/gWmuPs6/6:
let $context := .return ?store?book?*[?price <= $context?expensive]
:所有价格低于昂贵的书" - https://xqueryfiddle.liberty-development.net/gWmuPs6/7:
count(?store?book?*)
: 书的数量"
- https://xqueryfiddle.liberty-development.net/gWmuPs6/0 :
?store?book?*?author
: "the authors of all books" - https://xqueryfiddle.liberty-development.net/gWmuPs6/1 :
?store?*
: "all things in the store, both books and bicycles" - https://xqueryfiddle.liberty-development.net/gWmuPs6/2 :
?store?book?3
: "the third book" - https://xqueryfiddle.liberty-development.net/gWmuPs6/3 :
?store?book?(1,2)
: "the first two books" - https://xqueryfiddle.liberty-development.net/gWmuPs6/4 :
?store?book?*[?isbn]
: "all books with an isbn number" - https://xqueryfiddle.liberty-development.net/gWmuPs6/5 :
?store?book?*[?price < 10]
: "all books with a price less than 10" - https://xqueryfiddle.liberty-development.net/gWmuPs6/6 :
let $context := . return ?store?book?*[?price <= $context?expensive]
: "all books with a price less than expensive" - https://xqueryfiddle.liberty-development.net/gWmuPs6/7 :
count(?store?book?*)
: "the number of books"
文件是
{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
},
"expensive": 10
}
这篇关于如何将 JSON 文件加载到在 Java 中运行的 Saxon 中的 DOM?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!