Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2018-2023 Saxonica Limited
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
package net.sf.saxon.ma.json;
import net.sf.saxon.event.PipelineConfiguration;
import net.sf.saxon.event.Receiver;
import net.sf.saxon.expr.XPathContext;
import net.sf.saxon.functions.SystemFunction;
import net.sf.saxon.om.*;
import net.sf.saxon.s9api.Location;
import net.sf.saxon.str.*;
import net.sf.saxon.trans.Err;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.type.SchemaType;
import net.sf.saxon.type.StringConverter;
import net.sf.saxon.value.DoubleValue;
import net.sf.saxon.value.StringToDouble11;
import net.sf.saxon.value.StringValue;
import net.sf.saxon.value.Whitespace;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.Stack;
import java.util.function.IntPredicate;
/**
* A Receiver which receives a stream of XML events using the vocabulary defined for the XML representation
* of JSON in XSLT 3.0, and which generates the corresponding JSON text as a string
*/
public class JsonReceiver implements Receiver {
private XPathContext context;
private PipelineConfiguration pipe;
private UniStringConsumer output;
private final StringBuilder textBuffer = new StringBuilder(128);
private final Stack stack = new Stack<>();
private boolean atStart = true;
private boolean indenting = false;
private boolean escaped = false;
private final Stack> keyChecker = new Stack<>();
private FunctionItem numberFormatter = null;
private static final String ERR_INPUT = "FOJS0006";
public JsonReceiver(PipelineConfiguration pipe, XPathContext context, UniStringConsumer output) {
Objects.requireNonNull(pipe);
Objects.requireNonNull(output);
setPipelineConfiguration(pipe);
this.output = output;
this.context = context;
}
@Override
public void setPipelineConfiguration(PipelineConfiguration pipe) {
this.pipe = pipe;
}
@Override
public PipelineConfiguration getPipelineConfiguration() {
return pipe;
}
@Override
public void setSystemId(String systemId) {
// no action
}
public void setIndenting(boolean indenting) {
this.indenting = indenting;
}
public boolean isIndenting() {
return indenting;
}
public void setNumberFormatter(FunctionItem formatter) {
assert formatter.getArity() == 1;
this.numberFormatter = formatter;
}
public FunctionItem getNumberFormatter() {
return this.numberFormatter;
}
@Override
public void open() throws XPathException {
output.open();
}
@Override
public void startDocument(int properties) throws XPathException {
// if (output == null) {
// output = new StringBuilder(2048);
// }
}
@Override
public void endDocument() throws XPathException {
// no action
}
@Override
public void setUnparsedEntity(String name, String systemID, String publicID) throws XPathException {
// no action
}
@Override
public void startElement(NodeName elemName, SchemaType type,
AttributeMap attributes, NamespaceMap namespaces,
Location location, int properties) throws XPathException {
String parent = stack.empty() ? null : stack.peek().getLocalPart();
boolean inMap = "map".equals(parent) || stack.isEmpty();
stack.push(elemName);
//started.push(false);
if (!elemName.hasURI(NamespaceUri.FN)) {
throw new XPathException("xml-to-json: element found in wrong namespace: " +
elemName.getStructuredQName().getEQName(), ERR_INPUT);
}
String key = null;
String escapedAtt = null;
String escapedKey = null;
for (AttributeInfo att : attributes) {
NodeName attName = att.getNodeName();
if (attName.hasURI(NamespaceUri.NULL)) {
switch (attName.getLocalPart()) {
case "key":
if (!inMap) {
throw new XPathException(
"xml-to-json: The key attribute is allowed only on elements within a map", ERR_INPUT);
}
key = att.getValue();
break;
case "escaped-key":
if (!inMap) {
throw new XPathException(
"xml-to-json: The escaped-key attribute is allowed only on elements within a map", ERR_INPUT);
}
escapedKey = att.getValue();
break;
case "escaped":
boolean allowed = stack.size() == 1 || elemName.getLocalPart().equals("string");
// See bugs 29917 and 30077: at the top level, the escaped attribute is ignored
// whatever element it appears on
if (!allowed) {
throw new XPathException(
"xml-to-json: The escaped attribute is allowed only on the element",
ERR_INPUT);
}
escapedAtt = att.getValue();
break;
default:
throw new XPathException("xml-to-json: Disallowed attribute in input: " + attName.getDisplayName(), ERR_INPUT);
}
} else if (attName.hasURI(NamespaceUri.FN)) {
throw new XPathException("xml-to-json: Disallowed attribute in input: " + attName.getDisplayName(), ERR_INPUT);
}
// Attributes in other namespaces are ignored
}
if (!atStart) {
output.accept(BMPString.of(","));
if (indenting) {
indent(stack.size());
}
}
if (inMap && !keyChecker.isEmpty()) {
if (key == null) {
throw new XPathException("xml-to-json: Child elements of