0

在我的 Java 代码中,我试图创建一个作为 JSON 文件内容的 Saxon 文档 (DOM)。这应该是可能的,但我的代码失败了。

完整的代码位于SaxonQuestions.zip和 TestLoadJson.java 并且也在下面列出。在此代码中,evaluate() 失败。

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);
    }
}
4

1 回答 1

0

如果您有一个String带有 JSON 的 Java,将其作为变量传递给 XPath 并调用parse-json该变量:

    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 ):

    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 评估。

所以让我们假设你有employees.json包含

{ 
    "employees": [ 
        { 
          "name": "mike",
          "department": "accounting",
          "age": 34 
        },
        { 
          "name": "sally",
          "department": "sales",
          "age": 24
        }
      ]
}

然后您可以将其与第二个样本一起解析为 XdmValue 值,并将其进一步用作表达式的上下文项,例如

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每个数组项的值:

avg(?Students?*!(?Grade, 70)[1])

但是70对于那些没有Grade. 示例 JSON 是

{
  "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 项,作为进一步评估的上下文项。

为了给出一些针对 JSON 的更复杂的 XPath 3.1 表达式的示例,我从https://github.com/json-path/JsonPath中的路径示例中获取了 JSON 样本作为 JSON 输入parse-json(如果你有一个字符串)或者json-doc如果您有一个文件的 URI 甚至是 HTTP(S) 位置,并将其用作某些路径的上下文项(在小提琴中评估为 XQuery 3.1,但 XPath 3.1 是一个子集,我认为我已将示例限制为 XPath 3.1 :

样品位于:

该文件是

{
    "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
}
于 2020-07-26T21:45:39.260 回答