Skip to content
Commits on Source (6)
saxonhe (9.9.1.1+dfsg-1) unstable; urgency=medium
* New upstream release.
* Trim trailing whitespace.
* Use secure URI in Homepage field.
* Use secure copyright file specification URI.
* Bump Standards-Version to 4.4.0 (no changes)
-- Eugene Zhukov <eugene@debian.org> Tue, 23 Jul 2019 16:28:21 -0300
saxonhe (9.9.0.2+dfsg-1) unstable; urgency=medium
* New upstream release.
......
......@@ -15,10 +15,10 @@ Build-Depends: debhelper (>= 11),
libcommons-io-java,
libintellij-annotations-java,
libicu4j-java
Standards-Version: 4.2.1.3
Standards-Version: 4.4.0
Vcs-Git: https://salsa.debian.org/java-team/saxonhe.git
Vcs-Browser: https://salsa.debian.org/java-team/saxonhe
Homepage: http://www.saxonica.com/
Homepage: https://www.saxonica.com/
Package: libsaxonhe-java
Architecture: all
......@@ -32,4 +32,3 @@ Description: Saxon-HE is the XSLT and XQuery Processor
support for the 3.0 versions of the specifications; numerous Saxon extensions;
calling out to Java methods; XQuery Update support; various optimizations
including join optimization; streamed processing; and byte code generation.
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: Saxon-HE
Source: http://www.saxonica.com/
Comment: Tarball is repacked to remove folder with inappropriate license
......
......@@ -8,7 +8,7 @@ Description: Add pom.xml for building and packaging
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>net.sf.saxon</groupId>
+ <artifactId>Saxon-HE</artifactId>
+ <version>9.9.0.2</version>
+ <version>9.9.1.1</version>
+ <packaging>jar</packaging>
+ <name>Saxon-HE</name>
+ <description>The XSLT and XQuery Processor</description>
......
Description: Remove SaxonCAPI.debug statements
--- saxonhe-9.9.0.1+dfsg.orig/net/sf/saxon/jetonnet/JetPullProvider.java
+++ saxonhe-9.9.0.1+dfsg/net/sf/saxon/jetonnet/JetPullProvider.java
--- a/net/sf/saxon/jetonnet/JetPullProvider.java
+++ b/net/sf/saxon/jetonnet/JetPullProvider.java
@@ -6,7 +6,6 @@ import net.sf.saxon.expr.parser.Explicit
import net.sf.saxon.expr.parser.Location;
import net.sf.saxon.lib.ParseOptions;
......@@ -60,8 +60,8 @@ Description: Remove SaxonCAPI.debug statements
return new FingerprintedQName(prefix, namespaceURI, localName);
}
--- saxonhe-9.9.0.1+dfsg.orig/net/sf/saxon/jetonnet/JetStream.java
+++ saxonhe-9.9.0.1+dfsg/net/sf/saxon/jetonnet/JetStream.java
--- a/net/sf/saxon/jetonnet/JetStream.java
+++ b/net/sf/saxon/jetonnet/JetStream.java
@@ -3,7 +3,6 @@ package net.sf.saxon.jetonnet;
import net.sf.saxon.Configuration;
import net.sf.saxon.lib.ParseOptions;
......
......@@ -21,8 +21,8 @@ import net.sf.saxon.functions.*;
import net.sf.saxon.functions.registry.*;
import net.sf.saxon.lib.*;
import net.sf.saxon.ma.arrays.ArrayFunctionSet;
import net.sf.saxon.ma.map.HashTrieMap;
import net.sf.saxon.ma.map.MapFunctionSet;
import net.sf.saxon.ma.map.MapItem;
import net.sf.saxon.om.*;
import net.sf.saxon.pattern.PatternParser30;
import net.sf.saxon.pull.PullSource;
......@@ -44,6 +44,7 @@ import net.sf.saxon.trace.TraceCodeInjector;
import net.sf.saxon.trace.XSLTTraceCodeInjector;
import net.sf.saxon.trans.*;
import net.sf.saxon.trans.packages.IPackageLoader;
import net.sf.saxon.tree.tiny.TreeStatistics;
import net.sf.saxon.tree.util.DocumentNumberAllocator;
import net.sf.saxon.type.*;
import net.sf.saxon.value.*;
......@@ -193,6 +194,8 @@ public class Configuration implements SourceResolver, NotationSet {
protected int byteCodeThreshold = 100;
private int regexBacktrackingLimit = 10000000;
private TreeStatistics treeStatistics = new TreeStatistics();
/**
* Constant indicating that the processor should take the recovery action
* when a recoverable error occurs, with no warning message.
......@@ -1581,8 +1584,10 @@ public class Configuration implements SourceResolver, NotationSet {
*
* @param collationName the collation name as an absolute URI
* @return the StringCollator with this name if known, or null if not known
* @throws XPathException if the collation URI is recognized but is invalid in this
* environment.
* @throws XPathException if the collation URI is recognized but is invalid; for example,
* if it is a URI that takes parameters, and the parameters are invalid. If a user-supplied
* collation URI resolver is in use, then any exception thrown by that resolver is passed
* on to the caller.
*/
......@@ -1990,7 +1995,14 @@ public class Configuration implements SourceResolver, NotationSet {
public Numberer makeNumberer(/*@Nullable*/ String language, /*@Nullable*/ String country) {
if (localizerFactory == null) {
return new Numberer_en();
Numberer_en numberer = new Numberer_en();
if (language != null) {
numberer.setLanguage(language);
}
if (country != null) {
numberer.setCountry(country);
}
return numberer;
} else {
Numberer numberer = localizerFactory.getNumberer(language, country);
if (numberer == null) {
......@@ -2071,7 +2083,6 @@ public class Configuration implements SourceResolver, NotationSet {
/**
* Set the URI resolver to be used for resolving URIs passed to the unparsed-text(),
* unparsed-text-available(), and unparsed-text-lines() functions
*
* @param resolver the URI resolver to be used for these functions.
*/
......@@ -3938,7 +3949,7 @@ public class Configuration implements SourceResolver, NotationSet {
* @throws UnsupportedOperationException except in subclasses
*/
public HashTrieMap externalObjectAsMap(ObjectValue value, String required) {
public MapItem externalObjectAsMap(ObjectValue value, String required) {
throw new UnsupportedOperationException();
}
......@@ -4312,6 +4323,16 @@ public class Configuration implements SourceResolver, NotationSet {
return new DocumentInfo(root);
}
/**
* Get the collection of tree-builder statistics for this configuration, used
* for learning suitable amounts of space to allocate for different kinds of tree
* @return the object in which tree statistics are accumulated
*/
public TreeStatistics getTreeStatistics() {
return treeStatistics;
}
/**
* Load a named output emitter or SAX2 ContentHandler and check it is OK.
*
......@@ -4632,31 +4653,16 @@ public class Configuration implements SourceResolver, NotationSet {
break;
case FeatureCode.SCHEMA_VALIDATION: {
Object v = value;
if (v instanceof String) {
try {
v = Integer.parseInt((String) value);
} catch (NumberFormatException ex) {
throw new IllegalArgumentException("SCHEMA_VALIDATION must be an integer");
}
} else if (!(v instanceof Integer)) {
throw new IllegalArgumentException("SCHEMA_VALIDATION must be an integer");
}
setSchemaValidationMode((Integer) v);
setSchemaValidationMode(requireInteger(feature.name, value));
break;
}
case FeatureCode.SCHEMA_VALIDATION_MODE:
if (!(value instanceof String)) {
throw new IllegalArgumentException("SCHEMA_VALIDATION_MODE must be a string");
}
setSchemaValidationMode(Validation.getCode((String) value));
String mode = requireString(feature.name, value);
setSchemaValidationMode(Validation.getCode(mode));
break;
case FeatureCode.SOURCE_PARSER_CLASS:
if (!(value instanceof String)) {
throw new IllegalArgumentException("SOURCE_PARSER_CLASS class must be a String");
}
setSourceParserClass((String) value);
setSourceParserClass(requireString(feature.name, value));
break;
case FeatureCode.SOURCE_RESOLVER_CLASS:
......@@ -4678,7 +4684,6 @@ public class Configuration implements SourceResolver, NotationSet {
case FeatureCode.STRIP_WHITESPACE: {
String s = requireString(name, value);
int ival;
switch (s) {
case "all":
defaultParseOptions.setSpaceStrippingRule(AllElementsSpaceStrippingRule.getInstance());
......@@ -4792,8 +4797,8 @@ public class Configuration implements SourceResolver, NotationSet {
}
case FeatureCode.XPATH_VERSION_FOR_XSLT: {
int val = requireInteger(name, value);
if (val != 30 && val != 31) {
throw new IllegalArgumentException("XPath version for XSLT must be 30 (XPath 3.0) or 31 (XPath 3.1)");
if (val != 20 && val != 30 && val != 305 && val != 31) {
throw new IllegalArgumentException("XPath version for XSLT must be 20 (XPath 2.0), 30 (XPath 3.0), 31 (XPath 3.1), or 305 (XPath 3.0 with XSLT-defined extensions)");
}
xpathVersionForXslt = val;
break;
......@@ -4944,10 +4949,11 @@ public class Configuration implements SourceResolver, NotationSet {
* @throws IllegalArgumentException if the supplied value cannot be validated as a recognized boolean value
*/
protected boolean requireBoolean(String propertyName, Object value) {
public static boolean requireBoolean(String propertyName, Object value) {
if (value instanceof Boolean) {
return (Boolean) value;
} else if (value instanceof String) {
value = ((String)value).trim();
if ("true".equals(value) || "on".equals(value) || "yes".equals(value) || "1".equals(value)) {
return true;
} else if ("false".equals(value) || "off".equals(value) || "no".equals(value) || "0".equals(value)) {
......
......@@ -27,7 +27,6 @@ import net.sf.saxon.resource.CollectionURIResolverWrapper;
import net.sf.saxon.trace.TraceEventMulticaster;
import net.sf.saxon.trans.*;
import net.sf.saxon.trans.rules.RuleManager;
import net.sf.saxon.tree.tiny.Statistics;
import net.sf.saxon.tree.tiny.TinyBuilder;
import net.sf.saxon.tree.wrapper.SpaceStrippedDocument;
import net.sf.saxon.tree.wrapper.SpaceStrippedNode;
......@@ -606,6 +605,16 @@ public class Controller implements ContextOriginator {
this.globalContextItemPreset = true;
}
/**
* Reset the global context item to null. This clears any previous setting of the global context
* item.
*/
public void clearGlobalContextItem() {
this.globalContextItem = null;
this.globalContextItemPreset = false;
}
/**
* Get the item used as the context for evaluating global variables. In XQuery this
......@@ -1136,7 +1145,7 @@ public class Controller implements ContextOriginator {
* users (it is done automatically when transform() is invoked). However, it is available as a low-level API
* especially for use with XQuery.
*
* @param params the values of stylesheet parameters. Changed in 9.9.0.2 so this no longer includes
* @param params the values of stylesheet parameters. Changed in 9.9.1.1 so this no longer includes
* static parameters (which are already available in the {@link PreparedStylesheet}).
* @throws XPathException if an error occurs, for example if a required parameter is not supplied.
*/
......@@ -1311,7 +1320,7 @@ public class Controller implements ContextOriginator {
Builder sourceBuilder = makeBuilder();
sourceBuilder.setUseEventLocation(true);
if (sourceBuilder instanceof TinyBuilder) {
((TinyBuilder) sourceBuilder).setStatistics(Statistics.SOURCE_DOCUMENT_STATISTICS);
((TinyBuilder) sourceBuilder).setStatistics(config.getTreeStatistics().SOURCE_DOCUMENT_STATISTICS);
}
Receiver r = sourceBuilder;
SpaceStrippingRule spaceStrippingRule = NoElementsSpaceStrippingRule.getInstance();
......
......@@ -74,6 +74,7 @@ public class Query {
private boolean closeTraceDestination = false;
private boolean allowExit = true;
/**
* Get the configuration in use
*
......@@ -407,13 +408,7 @@ public class Query {
if (outputFile.isDirectory()) {
quit("Output is a directory", 2);
}
if (!outputFile.exists()) {
File directory = outputFile.getParentFile();
if (directory != null && !directory.exists()) {
directory.mkdirs();
}
outputFile.createNewFile();
}
createFileIfNecessary(outputFile);
out = new FileOutputStream(outputFile);
} else {
out = System.out;
......@@ -598,7 +593,7 @@ public class Query {
config.setTraceListener(listener);
config.setLineNumbering(true);
config.getDefaultStaticQueryContext().setCodeInjector(new TimingCodeInjector());
if (value.length() > 0) {
if (!value.isEmpty()) {
try {
listener.setOutputDestination(
new StandardLogger(new File(value)));
......@@ -1077,14 +1072,28 @@ public class Query {
System.err.println(" ?param=expression Set query parameter using XPath");
System.err.println(" !param=value Set serialization parameter");
if (allowExit) {
if ("".equals(message)) {
System.exit(0);
} else {
System.exit(2);
}
System.exit("".equals(message) ? 0 : 2);
} else {
throw new RuntimeException(message);
}
}
/**
* Utility method to create a file if it does not already exist, including creation of any
* necessary directories named in the file path
* @param file the file that is required to exist
* @throws IOException if file creation fails
*/
@SuppressWarnings("ResultOfMethodCallIgnored")
public static void createFileIfNecessary(File file) throws IOException {
if (!file.exists()) {
File directory = file.getParentFile();
if (directory != null && !directory.exists()) {
directory.mkdirs();
}
file.createNewFile();
}
}
}
......@@ -13,10 +13,11 @@ package net.sf.saxon;
public final class Version {
private static final int[] STRUCTURED_VERSION = {9, 9, 0, 2};
private static final String VERSION = "9.9.0.2";
private static final String BUILD = "110716"; //mmddhh
private static final String RELEASE_DATE = "2018-11-07";
private static final int[] STRUCTURED_VERSION = {9, 9, 1, 1};
private static final String VERSION = "9.9.1.1";
//private static final String VERSION = "9.9.0.2-20181108";
private static final String BUILD = "012115"; //mmddhh
private static final String RELEASE_DATE = "2019-01-21";
private static final String MAJOR_RELEASE_DATE = "2018-09-27";
private Version() {
......
<?xml version="1.0" encoding="UTF-8"?>
<scm:schema xmlns:scm="http://ns.saxonica.com/schema-component-model"
generatedAt="2018-09-21T14:03:43.752+01:00"
generatedAt="2019-01-17T15:41:29.343Z"
xsdVersion="1.1"
dmk="TGljZW5zb3I9U2F4b25pY2EKTGljZW5zZWU9TydOZWlsIERlbHByYXR0CkNvbXBhbnk9U2F4b25pY2EKRW1haWw9b25laWxAc2F4b25pY2EuY29tCkVkaXRpb249REUKU0FUPXllcwpTQVE9eWVzClNBVj15ZXMKSXNzdWVkPTIwMTctMTEtMjIKU2VyaWVzPUQKU2VyaWFsPUQwMDY0MDgKVXNlcj1QMDAwMQpFdmFsdWF0aW9uPW5vCkV4cGlyYXRpb249bmV2ZXIKVXBncmFkZURheXM9MzY2Ck1haW50ZW5hbmNlRGF5cz0zNjYKU2lnbmF0dXJlPTMwMkMwMjE0NjU1REM4QzZFRDM3NDBDOTg4MkFERkYzRUFBQzVGNDlDRTcwOTFGRDAyMTQzRjQ0N0Y4OEY1MTIxQTQxMUM3MTQwRThEMzMyQzQ3Q0E4RUZDQjE1Cg==">
dmk="TGljZW5zb3I9U2F4b25pY2EKTGljZW5zZWU9TydOZWlsIERlbHByYXR0CkNvbXBhbnk9U2F4b25pY2EKRW1haWw9b25laWxAc2F4b25pY2EuY29tCkVkaXRpb249REUKU0FUPXllcwpTQVE9eWVzClNBVj15ZXMKSXNzdWVkPTIwMTgtMDctMDQKU2VyaWVzPU8KU2VyaWFsPU8wMDcwNjIKVXNlcj1QMDAwMQpFdmFsdWF0aW9uPW5vCkV4cGlyYXRpb249bmV2ZXIKVXBncmFkZURheXM9MzY2Ck1haW50ZW5hbmNlRGF5cz0zNjYKClNpZ25hdHVyZT0zMDJDMDIxNDA1RDJEREQ0NjBGQzhFODI0OTEyMkEzQzVBNzZENzRDRDdFMjk2OTcwMjE0NUM5MTQxNjAyNzYzRTlBNjU0Qjc3MkM3NTk3RDg5RTNCQkE5MTAzQg==">
<scm:simpleType id="C0"
name="finiteNumberType"
targetNamespace="http://www.w3.org/2005/xpath-functions"
......@@ -20,7 +20,11 @@
abstract="false"
variety="empty">
<scm:attributeUse required="false" inheritable="false" ref="C2"/>
<scm:attributeUse required="false" inheritable="false" ref="C3" default="false"/>
<scm:attributeUse required="false" inheritable="false" ref="C3" default="false">
<scm:default lexicalForm="false">
<scm:item type="#boolean" value="false"/>
</scm:default>
</scm:attributeUse>
<scm:finiteStateMachine initialState="0">
<scm:state nr="0" final="true"/>
</scm:finiteStateMachine>
......@@ -46,8 +50,16 @@
variety="simple"
simpleType="#string">
<scm:attributeUse required="false" inheritable="false" ref="C2"/>
<scm:attributeUse required="false" inheritable="false" ref="C3" default="false"/>
<scm:attributeUse required="false" inheritable="false" ref="C8" default="false"/>
<scm:attributeUse required="false" inheritable="false" ref="C3" default="false">
<scm:default lexicalForm="false">
<scm:item type="#boolean" value="false"/>
</scm:default>
</scm:attributeUse>
<scm:attributeUse required="false" inheritable="false" ref="C8" default="false">
<scm:default lexicalForm="false">
<scm:item type="#boolean" value="false"/>
</scm:default>
</scm:attributeUse>
<scm:attributeWildcard ref="C9"/>
</scm:complexType>
<scm:complexType id="C10"
......@@ -80,20 +92,20 @@
</scm:modelGroupParticle>
<scm:finiteStateMachine initialState="0">
<scm:state nr="0" final="true">
<scm:edge term="C14" to="1"/>
<scm:edge term="C17" to="1"/>
<scm:edge term="C15" to="1"/>
<scm:edge term="C18" to="1"/>
<scm:edge term="C19" to="1"/>
<scm:edge term="C17" to="1"/>
<scm:edge term="C16" to="1"/>
</scm:state>
<scm:state nr="1" final="true">
<scm:edge term="C14" to="1"/>
<scm:edge term="C17" to="1"/>
<scm:edge term="C15" to="1"/>
</scm:state>
<scm:state nr="1" final="true">
<scm:edge term="C18" to="1"/>
<scm:edge term="C19" to="1"/>
<scm:edge term="C17" to="1"/>
<scm:edge term="C16" to="1"/>
<scm:edge term="C14" to="1"/>
<scm:edge term="C15" to="1"/>
</scm:state>
</scm:finiteStateMachine>
</scm:complexType>
......@@ -106,7 +118,11 @@
variety="simple"
simpleType="#boolean">
<scm:attributeUse required="false" inheritable="false" ref="C2"/>
<scm:attributeUse required="false" inheritable="false" ref="C3" default="false"/>
<scm:attributeUse required="false" inheritable="false" ref="C3" default="false">
<scm:default lexicalForm="false">
<scm:item type="#boolean" value="false"/>
</scm:default>
</scm:attributeUse>
<scm:attributeWildcard ref="C22"/>
</scm:complexType>
<scm:complexType id="C23"
......@@ -117,7 +133,11 @@
abstract="false"
variety="element-only">
<scm:attributeUse required="false" inheritable="false" ref="C2"/>
<scm:attributeUse required="false" inheritable="false" ref="C3" default="false"/>
<scm:attributeUse required="false" inheritable="false" ref="C3" default="false">
<scm:default lexicalForm="false">
<scm:item type="#boolean" value="false"/>
</scm:default>
</scm:attributeUse>
<scm:attributeWildcard ref="C13"/>
<scm:modelGroupParticle minOccurs="0" maxOccurs="unbounded">
<scm:choice>
......@@ -131,20 +151,20 @@
</scm:modelGroupParticle>
<scm:finiteStateMachine initialState="0">
<scm:state nr="0" final="true">
<scm:edge term="C14" to="1"/>
<scm:edge term="C17" to="1"/>
<scm:edge term="C15" to="1"/>
<scm:edge term="C18" to="1"/>
<scm:edge term="C19" to="1"/>
<scm:edge term="C17" to="1"/>
<scm:edge term="C16" to="1"/>
</scm:state>
<scm:state nr="1" final="true">
<scm:edge term="C14" to="1"/>
<scm:edge term="C17" to="1"/>
<scm:edge term="C15" to="1"/>
</scm:state>
<scm:state nr="1" final="true">
<scm:edge term="C18" to="1"/>
<scm:edge term="C19" to="1"/>
<scm:edge term="C17" to="1"/>
<scm:edge term="C16" to="1"/>
<scm:edge term="C14" to="1"/>
<scm:edge term="C15" to="1"/>
</scm:state>
</scm:finiteStateMachine>
</scm:complexType>
......@@ -178,20 +198,20 @@
</scm:modelGroupParticle>
<scm:finiteStateMachine initialState="0">
<scm:state nr="0" final="true">
<scm:edge term="C27" to="1"/>
<scm:edge term="C26" to="1"/>
<scm:edge term="C31" to="1"/>
<scm:edge term="C29" to="1"/>
<scm:edge term="C27" to="1"/>
<scm:edge term="C30" to="1"/>
<scm:edge term="C28" to="1"/>
<scm:edge term="C29" to="1"/>
<scm:edge term="C31" to="1"/>
</scm:state>
<scm:state nr="1" final="true">
<scm:edge term="C27" to="1"/>
<scm:edge term="C26" to="1"/>
<scm:edge term="C31" to="1"/>
<scm:edge term="C29" to="1"/>
<scm:edge term="C27" to="1"/>
<scm:edge term="C30" to="1"/>
<scm:edge term="C28" to="1"/>
<scm:edge term="C29" to="1"/>
<scm:edge term="C31" to="1"/>
</scm:state>
</scm:finiteStateMachine>
</scm:complexType>
......@@ -203,7 +223,11 @@
abstract="false"
variety="element-only">
<scm:attributeUse required="false" inheritable="false" ref="C2"/>
<scm:attributeUse required="false" inheritable="false" ref="C3" default="false"/>
<scm:attributeUse required="false" inheritable="false" ref="C3" default="false">
<scm:default lexicalForm="false">
<scm:item type="#boolean" value="false"/>
</scm:default>
</scm:attributeUse>
<scm:attributeWildcard ref="C25"/>
<scm:modelGroupParticle minOccurs="0" maxOccurs="unbounded">
<scm:choice>
......@@ -217,20 +241,20 @@
</scm:modelGroupParticle>
<scm:finiteStateMachine initialState="0">
<scm:state nr="0" final="true">
<scm:edge term="C27" to="1"/>
<scm:edge term="C26" to="1"/>
<scm:edge term="C31" to="1"/>
<scm:edge term="C29" to="1"/>
<scm:edge term="C27" to="1"/>
<scm:edge term="C30" to="1"/>
<scm:edge term="C28" to="1"/>
<scm:edge term="C29" to="1"/>
<scm:edge term="C31" to="1"/>
</scm:state>
<scm:state nr="1" final="true">
<scm:edge term="C27" to="1"/>
<scm:edge term="C26" to="1"/>
<scm:edge term="C31" to="1"/>
<scm:edge term="C29" to="1"/>
<scm:edge term="C27" to="1"/>
<scm:edge term="C30" to="1"/>
<scm:edge term="C28" to="1"/>
<scm:edge term="C29" to="1"/>
<scm:edge term="C31" to="1"/>
</scm:state>
</scm:finiteStateMachine>
</scm:complexType>
......@@ -243,7 +267,11 @@
variety="simple"
simpleType="C0">
<scm:attributeUse required="false" inheritable="false" ref="C2"/>
<scm:attributeUse required="false" inheritable="false" ref="C3" default="false"/>
<scm:attributeUse required="false" inheritable="false" ref="C3" default="false">
<scm:default lexicalForm="false">
<scm:item type="#boolean" value="false"/>
</scm:default>
</scm:attributeUse>
<scm:attributeWildcard ref="C11"/>
</scm:complexType>
<scm:complexType id="C34"
......@@ -261,12 +289,12 @@
</scm:modelGroupParticle>
<scm:finiteStateMachine initialState="0">
<scm:state nr="0" final="true">
<scm:edge term="C35" to="1"/>
<scm:edge term="C36" to="1"/>
<scm:edge term="C35" to="1"/>
</scm:state>
<scm:state nr="1" final="true">
<scm:edge term="C35" to="1"/>
<scm:edge term="C36" to="1"/>
<scm:edge term="C35" to="1"/>
</scm:state>
</scm:finiteStateMachine>
</scm:complexType>
......@@ -313,7 +341,11 @@
abstract="false"
variety="simple"
simpleType="#string">
<scm:attributeUse required="false" inheritable="false" ref="C8" default="false"/>
<scm:attributeUse required="false" inheritable="false" ref="C8" default="false">
<scm:default lexicalForm="false">
<scm:item type="#boolean" value="false"/>
</scm:default>
</scm:attributeUse>
<scm:attributeWildcard ref="C9"/>
</scm:complexType>
<scm:element id="C30"
......@@ -392,35 +424,41 @@
name="key-group"
targetNamespace="http://www.w3.org/2005/xpath-functions">
<scm:attributeUse required="false" inheritable="false" ref="C2"/>
<scm:attributeUse required="false" inheritable="false" ref="C3" default="false"/>
<scm:attributeUse required="false" inheritable="false" ref="C3" default="false">
<scm:default lexicalForm="false">
<scm:item type="#boolean" value="false"/>
</scm:default>
</scm:attributeUse>
</scm:attributeGroup>
<scm:element id="C18"
name="boolean"
targetNamespace="http://www.w3.org/2005/xpath-functions"
type="C20"
<scm:attribute id="C2"
name="key"
type="#string"
global="false"
containingComplexType="C12"
nillable="false"
abstract="false"/>
<scm:element id="C19"
name="null"
targetNamespace="http://www.w3.org/2005/xpath-functions"
type="C1"
inheritable="false"/>
<scm:attribute id="C3"
name="escaped-key"
type="#boolean"
global="false"
containingComplexType="C12"
nillable="false"
abstract="false"/>
<scm:attribute id="C40"
name="nr"
type="#positiveInteger"
inheritable="false"/>
<scm:wildcard id="C5"
processContents="skip"
constraint="not"
namespaces="##local http://www.w3.org/2005/xpath-functions"/>
<scm:attribute id="C8"
name="escaped"
type="#boolean"
global="false"
inheritable="false"
containingComplexType="C39"/>
<scm:wildcard id="C5"
containingComplexType="C7"/>
<scm:wildcard id="C9"
processContents="skip"
constraint="not"
namespaces="##local http://www.w3.org/2005/xpath-functions"/>
<scm:wildcard id="C22"
<scm:wildcard id="C11"
processContents="skip"
constraint="not"
namespaces="##local http://www.w3.org/2005/xpath-functions"/>
<scm:wildcard id="C13"
processContents="skip"
constraint="not"
namespaces="##local http://www.w3.org/2005/xpath-functions"/>
......@@ -434,20 +472,6 @@
abstract="false">
<scm:identityConstraint ref="C44"/>
</scm:element>
<scm:unique id="C44"
name="unique-key-2"
targetNamespace="http://www.w3.org/2005/xpath-functions">
<scm:selector xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:j="http://www.w3.org/2005/xpath-functions"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xpath="*"
defaultNamespace=""/>
<scm:field xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:j="http://www.w3.org/2005/xpath-functions"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xpath="@key"
defaultNamespace=""/>
</scm:unique>
<scm:element id="C15"
name="array"
targetNamespace="http://www.w3.org/2005/xpath-functions"
......@@ -464,20 +488,6 @@
containingComplexType="C12"
nillable="false"
abstract="false"/>
<scm:unique id="C42"
name="unique-key"
targetNamespace="http://www.w3.org/2005/xpath-functions">
<scm:selector xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:j="http://www.w3.org/2005/xpath-functions"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xpath="*"
defaultNamespace=""/>
<scm:field xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:j="http://www.w3.org/2005/xpath-functions"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xpath="@key"
defaultNamespace=""/>
</scm:unique>
<scm:element id="C17"
name="number"
targetNamespace="http://www.w3.org/2005/xpath-functions"
......@@ -486,18 +496,23 @@
containingComplexType="C12"
nillable="false"
abstract="false"/>
<scm:attribute id="C8"
name="escaped"
type="#boolean"
<scm:element id="C18"
name="boolean"
targetNamespace="http://www.w3.org/2005/xpath-functions"
type="C20"
global="false"
inheritable="false"
containingComplexType="C7"/>
<scm:attribute id="C2"
name="key"
type="#string"
containingComplexType="C12"
nillable="false"
abstract="false"/>
<scm:element id="C19"
name="null"
targetNamespace="http://www.w3.org/2005/xpath-functions"
type="C1"
global="false"
inheritable="false"/>
<scm:wildcard id="C9"
containingComplexType="C12"
nillable="false"
abstract="false"/>
<scm:wildcard id="C22"
processContents="skip"
constraint="not"
namespaces="##local http://www.w3.org/2005/xpath-functions"/>
......@@ -505,18 +520,39 @@
processContents="skip"
constraint="not"
namespaces="##local http://www.w3.org/2005/xpath-functions"/>
<scm:attribute id="C3"
name="escaped-key"
type="#boolean"
<scm:attribute id="C40"
name="nr"
type="#positiveInteger"
global="false"
inheritable="false"/>
<scm:wildcard id="C13"
processContents="skip"
constraint="not"
namespaces="##local http://www.w3.org/2005/xpath-functions"/>
<scm:wildcard id="C11"
processContents="skip"
constraint="not"
namespaces="##local http://www.w3.org/2005/xpath-functions"/>
inheritable="false"
containingComplexType="C39"/>
<scm:unique id="C42"
name="unique-key"
targetNamespace="http://www.w3.org/2005/xpath-functions">
<scm:selector xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:j="http://www.w3.org/2005/xpath-functions"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xpath="*"
defaultNamespace=""/>
<scm:field xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:j="http://www.w3.org/2005/xpath-functions"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xpath="@key"
defaultNamespace=""/>
</scm:unique>
<scm:unique id="C44"
name="unique-key-2"
targetNamespace="http://www.w3.org/2005/xpath-functions">
<scm:selector xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:j="http://www.w3.org/2005/xpath-functions"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xpath="*"
defaultNamespace=""/>
<scm:field xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:j="http://www.w3.org/2005/xpath-functions"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xpath="@key"
defaultNamespace=""/>
</scm:unique>
</scm:schema>
<?Σ 8dedbd04?>
<?Σ 706ac2ac?>
......@@ -12,7 +12,6 @@ import net.sf.saxon.event.Sender;
import net.sf.saxon.lib.ParseOptions;
import net.sf.saxon.lib.Validation;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.tree.tiny.Statistics;
import net.sf.saxon.tree.tiny.TinyBuilder;
import net.sf.saxon.tree.tiny.TinyDocumentImpl;
import org.w3c.dom.DOMImplementation;
......@@ -144,7 +143,7 @@ public class DocumentBuilderImpl extends DocumentBuilder {
config = new Configuration();
}
TinyBuilder builder = new TinyBuilder(config.makePipelineConfiguration());
builder.setStatistics(Statistics.SOURCE_DOCUMENT_STATISTICS);
builder.setStatistics(config.getTreeStatistics().SOURCE_DOCUMENT_STATISTICS);
SAXSource source = new SAXSource(in);
source.setSystemId(in.getSystemId());
Sender.send(source, builder, parseOptions);
......
......@@ -12,7 +12,6 @@ import net.sf.saxon.om.NamePool;
import net.sf.saxon.om.NodeInfo;
import net.sf.saxon.pattern.NameTest;
import net.sf.saxon.tree.iter.AxisIterator;
import net.sf.saxon.tree.util.Navigator;
import net.sf.saxon.type.BuiltInAtomicType;
import net.sf.saxon.type.SchemaType;
import net.sf.saxon.type.Type;
......@@ -167,7 +166,8 @@ public class ElementOverNodeInfo extends NodeOverNodeInfo implements Element {
*/
public String getAttributeNS(String namespaceURI, String localName) {
String val = Navigator.getAttributeValue(node, namespaceURI == null ? "" : namespaceURI, localName);
String uri = namespaceURI == null ? "" : namespaceURI;
String val = node.getAttributeValue(uri, localName);
if (val == null) {
return "";
}
......@@ -297,7 +297,8 @@ public class ElementOverNodeInfo extends NodeOverNodeInfo implements Element {
*/
public boolean hasAttributeNS(String namespaceURI, String localName) {
return Navigator.getAttributeValue(node, namespaceURI == null ? "" : namespaceURI, localName) != null;
String uri = namespaceURI == null ? "" : namespaceURI;
return node.getAttributeValue(uri, localName) != null;
}
/**
......
......@@ -188,7 +188,7 @@ public class CheckSumFilter extends ProxyReceiver {
*/
public boolean isChecksumCorrect() {
return checksumCorrect;
return checksumCorrect || "skip".equals(System.getProperty("saxon-checksum"));
}
private int hash(CharSequence s, int sequence) {
......
......@@ -16,6 +16,8 @@ import net.sf.saxon.lib.Validation;
import net.sf.saxon.om.*;
import net.sf.saxon.trans.Err;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.tree.tiny.TinyBuilder;
import net.sf.saxon.tree.tiny.TinyElementImpl;
import net.sf.saxon.type.BuiltInAtomicType;
import net.sf.saxon.type.SchemaType;
import net.sf.saxon.type.SimpleType;
......@@ -303,11 +305,10 @@ public final class ComplexContentOutputter extends SequenceReceiver {
public void namespace(NamespaceBindingSet nsBindings, int properties)
throws XPathException {
// Optimization for recursive shallow-copy added in 9.8 - see bug 3011.
if (nsBindings instanceof InScopeNamespaces) {
copyNamespacesStack[level] = (InScopeNamespaces)nsBindings;
if (level > 1 && copyNamespacesStack[level - 1] != null &&
if (level > 0 && copyNamespacesStack[level - 1] != null &&
copyNamespacesStack[level - 1].getElement().equals(((InScopeNamespaces)nsBindings).getElement())) {
// Ignore these namespaces if they are the same as the namespaces for the parent element
return;
......@@ -333,11 +334,10 @@ public final class ComplexContentOutputter extends SequenceReceiver {
boolean rejectDuplicates = (properties & ReceiverOptions.REJECT_DUPLICATES) != 0;
for (int i = 0; i < pendingNSListSize; i++) {
if (nsBindings.equals(pendingNSList[i])) {
// same prefix and URI: ignore this duplicate
return;
}
if (ns.getPrefix().equals(pendingNSList[i].getPrefix())) {
if (ns.getURI().equals(pendingNSList[i].getURI())) {
return; // duplicate namespace, no action needed
}
if (pendingNSList[i].isDefaultUndeclaration() || ns.isDefaultUndeclaration()) {
// xmlns="" overridden by xmlns="abc"
pendingNSList[i] = ns;
......@@ -398,7 +398,7 @@ public final class ComplexContentOutputter extends SequenceReceiver {
*/
public void attribute(NodeName attName, SimpleType typeCode, CharSequence value, Location locationId, int properties) throws XPathException {
//System.err.println("Write attribute " + nameCode + "=" + value + " to Outputter " + this);
//System.err.println("Write attribute " + attName + "=" + value + " to Outputter " + this);
if (level >= 0 && state != StartTag) {
// The complexity here is in identifying the right error message and error code
......@@ -412,10 +412,10 @@ public final class ComplexContentOutputter extends SequenceReceiver {
throw err;
}
// if this is a duplicate attribute, overwrite the original, unless
// the REJECT_DUPLICATES option is set.
// if this is a duplicate attribute, overwrite the original in XSLT; throw an error in XQuery.
// No check needed if the NOT_A_DUPLICATE property is set (typically, during a deep copy operation)
if (level >= 0) {
if (level >= 0 && ((properties & ReceiverOptions.NOT_A_DUPLICATE)==0)) {
for (int a = 0; a < pendingAttListSize; a++) {
if (pendingAttCode[a].equals(attName)) {
if (hostLanguage == Configuration.XSLT) {
......@@ -680,14 +680,60 @@ public final class ComplexContentOutputter extends SequenceReceiver {
return nextReceiver.usesTypeAnnotations();
}
public void beforeBulkCopy() throws XPathException {
public boolean isReadyForGrafting() {
Receiver r2 = getReceiver();
if (r2 instanceof NamespaceReducer) {
if (!((NamespaceReducer) r2).isDisinheritingNamespaces()) {
Receiver r3 = ((NamespaceReducer) r2).getNextReceiver();
return r3 instanceof TinyBuilder &&
((state == StartTag &&
(startElementProperties & ReceiverOptions.DISINHERIT_NAMESPACES) == 0)
|| ((TinyBuilder) r3).isPositionedAtElement());
}
}
return false;
}
public void graftElementNode(TinyElementImpl elementNode, int copyOptions) throws XPathException {
NamespaceReducer r2 = (NamespaceReducer)getReceiver();
TinyBuilder target = (TinyBuilder)r2.getNextReceiver();
beforeBulkCopy();
boolean copyNamespaces = CopyOptions.includes(copyOptions, CopyOptions.ALL_NAMESPACES);
target.graft(elementNode, copyNamespaces);
afterBulkCopy();
}
public boolean isReadyForBulkCopy() {
Receiver r2 = getReceiver();
if (r2 instanceof NamespaceReducer) {
if (!((NamespaceReducer) r2).isDisinheritingNamespaces()) {
Receiver r3 = ((NamespaceReducer) r2).getNextReceiver();
return r3 instanceof TinyBuilder &&
((state == StartTag &&
(startElementProperties & ReceiverOptions.DISINHERIT_NAMESPACES) == 0)
|| ((TinyBuilder) r3).isPositionedAtElement());
}
}
return false;
}
public void bulkCopyElementNode(TinyElementImpl elementNode, int copyOptions) throws XPathException {
NamespaceReducer r2 = (NamespaceReducer) getReceiver();
TinyBuilder target = (TinyBuilder) r2.getNextReceiver();
beforeBulkCopy();
boolean copyNamespaces = CopyOptions.includes(copyOptions, CopyOptions.ALL_NAMESPACES);
target.bulkCopy(elementNode, copyNamespaces);
afterBulkCopy();
}
private void beforeBulkCopy() throws XPathException {
level++;
if (state == StartTag) {
startContent();
}
}
public void afterBulkCopy() {
private void afterBulkCopy() {
level--;
previousAtomic = false;
}
......
......@@ -39,7 +39,7 @@ public class ReceiverOptions {
public static final int NO_SPECIAL_CHARS = 4;
/**
* Flag indicating that an attribute value was added by the schema processor
* Flag indicating that an attribute value or text node was added by the schema processor
* because a default value was specified
*/
......@@ -151,6 +151,11 @@ public class ReceiverOptions {
*/
public static final int ALL_NAMESPACES = 0x80000;
/**
* Flag set on attribute() to indicate that there is no need to check for duplicate attributes
*/
public static final int NOT_A_DUPLICATE = 0x100000;
}
......@@ -12,6 +12,7 @@ import net.sf.saxon.expr.parser.Location;
import net.sf.saxon.om.*;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.tree.linked.LinkedTreeBuilder;
import net.sf.saxon.tree.tiny.TinyElementImpl;
import net.sf.saxon.tree.util.Orphan;
import net.sf.saxon.type.SchemaType;
import net.sf.saxon.type.SimpleType;
......@@ -148,6 +149,7 @@ public abstract class SequenceWriter extends SequenceReceiver {
NodeInfo doc = builder.getCurrentRoot();
// add the constructed document to the result sequence
append(doc, ExplicitLocation.UNKNOWN_LOCATION, ReceiverOptions.ALL_NAMESPACES);
systemId = null;
}
previousAtomic = false;
}
......@@ -181,6 +183,7 @@ public abstract class SequenceWriter extends SequenceReceiver {
outputter = null;
NodeInfo element = builder.getCurrentRoot();
append(element, ExplicitLocation.UNKNOWN_LOCATION, ReceiverOptions.ALL_NAMESPACES);
systemId = null;
}
previousAtomic = false;
}
......@@ -300,5 +303,30 @@ public abstract class SequenceWriter extends SequenceReceiver {
public boolean usesTypeAnnotations() {
return outputter == null || outputter.usesTypeAnnotations();
}
public boolean isReadyForBulkCopy() {
return level > 0 && outputter instanceof ComplexContentOutputter &&
((ComplexContentOutputter)outputter).isReadyForBulkCopy();
}
public void bulkCopyElementNode(TinyElementImpl node, int copyOptions) throws XPathException {
if (inStartTag) {
startContent();
}
((ComplexContentOutputter) outputter).bulkCopyElementNode(node, copyOptions);
}
public boolean isReadyForGrafting() {
return level > 0 && outputter instanceof ComplexContentOutputter &&
((ComplexContentOutputter) outputter).isReadyForGrafting();
}
public void graftElementNode(TinyElementImpl node, int copyOptions) throws XPathException {
if (inStartTag) {
startContent();
}
((ComplexContentOutputter) outputter).graftElementNode(node, copyOptions);
}
}
......@@ -37,16 +37,19 @@ public final class Atomizer extends UnaryExpression {
private boolean untyped = false; //set to true if it is known that the nodes being atomized will be untyped
private boolean singleValued = false; // set to true if all atomized nodes will atomize to a single atomic value
/*@Nullable*/ private ItemType operandItemType = null;
private ItemType operandItemType = null;
private RoleDiagnostic roleDiagnostic = null;
/**
* Constructor
*
* @param sequence the sequence to be atomized
* @param role (may be null) additional information for use in diagnostics
*/
public Atomizer(Expression sequence) {
public Atomizer(Expression sequence, RoleDiagnostic role) {
super(sequence);
this.roleDiagnostic = role;
sequence.setFlattened(true);
}
......@@ -54,14 +57,15 @@ public final class Atomizer extends UnaryExpression {
* Make an atomizer with a given operand
*
* @param sequence the operand
* @param role (may be null) additional information for diagnostics
* @return an Atomizer that atomizes the given operand, or another expression that returns the same result
*/
public static Expression makeAtomizer(Expression sequence) {
public static Expression makeAtomizer(Expression sequence, RoleDiagnostic role) {
if (sequence instanceof Literal && ((Literal) sequence).getValue() instanceof AtomicSequence) {
return sequence;
} else {
return new Atomizer(sequence);
return new Atomizer(sequence, role);
}
}
......@@ -116,12 +120,14 @@ public final class Atomizer extends UnaryExpression {
if (((Function)i).isArray()) {
return this;
} else if (((Function)i).isMap()) {
XPathException err = new XPathException("Cannot atomize a map", "FOTY0013");
XPathException err = new XPathException(
expandMessage("Cannot atomize a map (" + i.toShortString() + ")"), "FOTY0013");
err.setIsTypeError(true);
err.setLocation(getLocation());
throw err;
} else {
XPathException err = new XPathException("Cannot atomize a function item", "FOTY0013");
XPathException err = new XPathException(
expandMessage("Cannot atomize a function item"), "FOTY0013");
err.setIsTypeError(true);
err.setLocation(getLocation());
throw err;
......@@ -161,10 +167,10 @@ public final class Atomizer extends UnaryExpression {
if (operandType instanceof FunctionItemType) {
String thing = operandType instanceof MapType ? "map" : "function item";
err = new XPathException(
"Cannot atomize a " + thing, "FOTY0013");
expandMessage("Cannot atomize a " + thing), "FOTY0013");
} else {
err = new XPathException(
"Cannot atomize an element that is defined in the schema to have element-only content", "FOTY0012");
expandMessage("Cannot atomize an element that is defined in the schema to have element-only content"), "FOTY0012");
}
err.setIsTypeError(true);
err.setLocation(getLocation());
......@@ -195,6 +201,19 @@ public final class Atomizer extends UnaryExpression {
}
}
/**
* Expand an error message with information about the context in which atomization is taking place
* @param message the message to be expanded
*/
private String expandMessage(String message) {
if (roleDiagnostic == null) {
return message;
} else {
return message + ". Found while atomizing the " + roleDiagnostic.getMessage();
}
}
/**
* Perform optimisation of an expression and its subexpressions.
......@@ -229,7 +248,7 @@ public final class Atomizer extends UnaryExpression {
if (operand instanceof LetExpression || operand instanceof ForExpression) {
// replace data(let $x := y return z) by (let $x := y return data(z))
Expression action = ((Assignation) operand).getAction();
((Assignation) operand).setAction(new Atomizer(action));
((Assignation) operand).setAction(new Atomizer(action, roleDiagnostic));
return operand.optimize(visitor, contextInfo);
}
if (operand instanceof Choose) {
......@@ -243,23 +262,21 @@ public final class Atomizer extends UnaryExpression {
Operand[] children = ((Block) operand).getOperanda();
Expression[] atomizedChildren = new Expression[children.length];
for (int i = 0; i < children.length; i++) {
atomizedChildren[i] = new Atomizer(children[i].getChildExpression());
atomizedChildren[i] = new Atomizer(children[i].getChildExpression(), roleDiagnostic);
}
Block newBlock = new Block(atomizedChildren);
return newBlock.typeCheck(visitor, contextInfo).optimize(visitor, contextInfo);
}
if (untyped && operand instanceof AxisExpression &&
((AxisExpression)operand).getAxis() == AxisInfo.ATTRIBUTE &&
((AxisExpression) operand).getNodeTest() instanceof NameTest) {
((AxisExpression) operand).getNodeTest() instanceof NameTest &&
!((AxisExpression) operand).isContextPossiblyUndefined()) {
StructuredQName name = ((AxisExpression) operand).getNodeTest().getMatchingNodeName();
FingerprintedQName qName = new FingerprintedQName(name, visitor.getConfiguration().getNamePool());
AttributeGetter ag = new AttributeGetter(qName);
int checks = 0;
if (((AxisExpression) operand).isContextPossiblyUndefined()) {
checks |= AttributeGetter.CHECK_CONTEXT_ITEM_PRESENT;
}
if (!(((AxisExpression) operand).getContextItemType() instanceof NodeTest)) {
checks |= AttributeGetter.CHECK_CONTEXT_ITEM_IS_NODE;
checks = AttributeGetter.CHECK_CONTEXT_ITEM_IS_NODE;
}
ag.setRequiredChecks(checks);
ExpressionTool.copyLocationInfo(this, ag);
......@@ -310,7 +327,7 @@ public final class Atomizer extends UnaryExpression {
/*@NotNull*/
public Expression copy(RebindingMap rebindings) {
Atomizer copy = new Atomizer(getBaseExpression().copy(rebindings));
Atomizer copy = new Atomizer(getBaseExpression().copy(rebindings), roleDiagnostic);
copy.untyped = untyped;
copy.singleValued = singleValued;
ExpressionTool.copyLocationInfo(this, copy);
......@@ -328,8 +345,20 @@ public final class Atomizer extends UnaryExpression {
/*@NotNull*/
public SequenceIterator<?> iterate(XPathContext context) throws XPathException {
try {
SequenceIterator base = getBaseExpression().iterate(context);
return getAtomizingIterator(base, untyped && operandItemType instanceof NodeTest);
} catch (XPathException e) {
if (roleDiagnostic == null) {
throw e;
} else {
String message = e.getMessage() + ". Failed while atomizing the " + roleDiagnostic.getMessage();
XPathException e2 = new XPathException(message, e.getErrorCodeLocalPart(), e.getLocator());
e2.setXPathContext(context);
e2.maybeSetLocation(getLocation());
throw e2;
}
}
}
/**
......
......@@ -31,11 +31,11 @@ import net.sf.saxon.value.UntypedAtomicValue;
public final class AttributeGetter extends Expression {
public static final int CHECK_CONTEXT_ITEM_PRESENT = 1;
//public static final int CHECK_CONTEXT_ITEM_PRESENT = 1;
public static final int CHECK_CONTEXT_ITEM_IS_NODE = 2;
private FingerprintedQName attributeName;
private int requiredChecks = CHECK_CONTEXT_ITEM_PRESENT | CHECK_CONTEXT_ITEM_IS_NODE;
private int requiredChecks = CHECK_CONTEXT_ITEM_IS_NODE;
public AttributeGetter(FingerprintedQName attributeName) {
this.attributeName = attributeName;
......@@ -107,6 +107,7 @@ public final class AttributeGetter extends Expression {
return val == null ? null : new UntypedAtomicValue(val);
}
if (item == null) {
// This doesn't actually happen, we don't create an AttributeGetter unless we know statically
dynamicError("The context item for @" + attributeName.getDisplayName() +
" is absent", "XPDY0002", context);
}
......
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2018 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.expr;
import net.sf.saxon.expr.parser.*;
import net.sf.saxon.lib.ConversionRules;
import net.sf.saxon.om.*;
import net.sf.saxon.trace.ExpressionPresenter;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.tree.iter.EmptyIterator;
import net.sf.saxon.type.*;
import net.sf.saxon.value.AtomicValue;
import net.sf.saxon.value.Cardinality;
import net.sf.saxon.value.SequenceType;
/**
* Expression class for a cast to a List type
*/
public class CastToList extends UnaryExpression {
private ListType targetType;
private boolean allowEmpty;
public CastToList(Expression source, ListType targetType, boolean allowEmpty) {
super(source);
this.targetType = targetType;
this.allowEmpty = allowEmpty;
}
public boolean isAllowEmpty() {
return allowEmpty;
}
public ListType getTargetType() {
return targetType;
}
public NamespaceResolver getNamespaceResolver() {
return getRetainedStaticContext();
}
protected OperandRole getOperandRole() {
return OperandRole.SINGLE_ATOMIC;
}
/**
* Type-check the expression
*/
/*@NotNull*/
public Expression typeCheck(ExpressionVisitor visitor, ContextItemStaticInfo contextInfo) throws XPathException {
getOperand().typeCheck(visitor, contextInfo);
SequenceType atomicType = SequenceType.makeSequenceType(
BuiltInAtomicType.STRING,
allowEmpty ? StaticProperty.ALLOWS_ZERO_OR_ONE : StaticProperty.EXACTLY_ONE);
RoleDiagnostic role = new RoleDiagnostic(RoleDiagnostic.TYPE_OP, "cast as", 0);
Expression operand = visitor.getConfiguration().getTypeChecker(false).staticTypeCheck(
getBaseExpression(), atomicType, role, visitor);
setBaseExpression(operand);
final TypeHierarchy th = visitor.getConfiguration().getTypeHierarchy();
boolean maybeString = th.relationship(operand.getItemType(), BuiltInAtomicType.STRING) != TypeHierarchy.DISJOINT;
boolean maybeUntyped = th.relationship(operand.getItemType(), BuiltInAtomicType.UNTYPED_ATOMIC) != TypeHierarchy.DISJOINT;
if (!maybeString && !maybeUntyped) {
XPathException err = new XPathException("Casting to list requires an xs:string or xs:untypedAtomic operand");
err.setErrorCode("XPTY0004");
err.setLocation(getLocation());
err.setIsTypeError(true);
throw err;
}
if (operand instanceof Literal) {
GroundedValue literalOperand = ((Literal) operand).getValue();
if (literalOperand instanceof AtomicValue) {
try {
SequenceIterator<?> seq =
iterate(visitor.getStaticContext().makeEarlyEvaluationContext());
return Literal.makeLiteral(seq.materialize(), this);
} catch (XPathException err) {
err.maybeSetErrorCode("FORG0001");
err.setLocation(getLocation());
err.setIsTypeError(true);
throw err;
}
}
if (literalOperand.getLength() == 0) {
if (allowEmpty) {
return operand;
} else {
XPathException err = new XPathException("Cast can never succeed: the operand must not be an empty sequence");
err.setErrorCode("XPTY0004");
err.setLocation(getLocation());
err.setIsTypeError(true);
throw err;
}
}
}
return this;
}
/**
* Perform optimisation of an expression and its subexpressions.
* <p>This method is called after all references to functions and variables have been resolved
* to the declaration of the function or variable, and after all type checking has been done.</p>
*
* @param visitor an expression visitor
* @param contextInfo the static type of "." at the point where this expression is invoked.
* The parameter is set to null if it is known statically that the context item will be undefined.
* If the type of the context item is not known statically, the argument is set to
* {@link net.sf.saxon.type.Type#ITEM_TYPE}
* @return the original expression, rewritten if appropriate to optimize execution
* @throws net.sf.saxon.trans.XPathException
* if an error is discovered during this phase
* (typically a type error)
*/
/*@NotNull*/
public Expression optimize(ExpressionVisitor visitor, ContextItemStaticInfo contextInfo) throws XPathException {
Expression e2 = super.optimize(visitor, contextInfo);
if (e2 != this) {
return e2;
}
// if the operand can't be empty, then set allowEmpty to false to provide more information for analysis
if (!Cardinality.allowsZero(getBaseExpression().getCardinality())) {
allowEmpty = false;
resetLocalStaticProperties();
}
return this;
}
/**
* Get the static cardinality of the expression
*/
public int computeCardinality() {
return StaticProperty.ALLOWS_ZERO_OR_MORE;
}
/**
* Get the expression's dependencies. If the target type is namespace-sensitive, then the expression
* has a dependency on the namespace bindings in the static context
*
* @return the expression's dependencies.
*/
@Override
public int getIntrinsicDependencies() {
return getTargetType().isNamespaceSensitive() ? StaticProperty.DEPENDS_ON_STATIC_CONTEXT : 0;
}
/**
* Get the static type of the expression
*/
/*@NotNull*/
public ItemType getItemType() {
try {
if (targetType.getItemType() instanceof ItemType) {
return (ItemType) targetType.getItemType();
}
} catch (MissingComponentException e) {
//
}
return BuiltInAtomicType.ANY_ATOMIC;
}
/**
* Get the static type of the expression as a UType, following precisely the type
* inference rules defined in the XSLT 3.0 specification.
*
* @return the static item type of the expression according to the XSLT 3.0 defined rules
* @param contextItemType
*/
@Override
public UType getStaticUType(UType contextItemType) {
return UType.ANY_ATOMIC;
}
/**
* Determine the special properties of this expression
*
* @return {@link net.sf.saxon.expr.StaticProperty#NO_NODES_NEWLY_CREATED}.
*/
public int computeSpecialProperties() {
int p = super.computeSpecialProperties();
return p | StaticProperty.NO_NODES_NEWLY_CREATED;
}
/**
* Copy an expression. This makes a deep copy.
*
* @return the copy of the original expression
* @param rebindings
*/
/*@NotNull*/
public Expression copy(RebindingMap rebindings) {
CastToList c = new CastToList(getBaseExpression().copy(rebindings), targetType, allowEmpty);
ExpressionTool.copyLocationInfo(this, c);
c.setRetainedStaticContext(getRetainedStaticContext());
return c;
}
/**
* An implementation of Expression must provide at least one of the methods evaluateItem(), iterate(), or process().
* This method indicates which of these methods is provided directly. The other methods will always be available
* indirectly, using an implementation that relies on one of the other methods.
*
* @return the implementation method, for example {@link #ITERATE_METHOD} or {@link #EVALUATE_METHOD} or
* {@link #PROCESS_METHOD}
*/
@Override
public int getImplementationMethod() {
return ITERATE_METHOD;
}
/**
* Evaluate the expression
*/
public SequenceIterator<?> iterate(XPathContext context) throws XPathException {
AtomicValue value = (AtomicValue) getBaseExpression().evaluateItem(context);
if (value == null) {
if (allowEmpty) {
return EmptyIterator.emptyIterator();
} else {
XPathException e = new XPathException("Cast does not allow an empty sequence");
e.setXPathContext(context);
e.setLocation(getLocation());
e.setErrorCode("XPTY0004");
throw e;
}
}
return cast(value.getStringValueCS(), targetType, getRetainedStaticContext(),
context.getConfiguration().getConversionRules()).iterate();
}
/**
* Cast a string value to a list type
*
* @param value the input string value
* @param targetType the target list type
* @param nsResolver the namespace context, needed if the type is namespace-sensitive
* @param rules the conversion rules
* @return the sequence of atomic values that results from the conversion
* @throws XPathException if the conversion fails
*/
public static AtomicSequence cast(CharSequence value, ListType targetType, final NamespaceResolver nsResolver, final ConversionRules rules)
throws XPathException {
ValidationFailure failure = targetType.validateContent(value, nsResolver, rules);
if (failure != null) {
throw failure.makeException();
}
return targetType.getTypedValue(value, nsResolver, rules);
}
/**
* Is this expression the same as another expression?
*/
public boolean equals(Object other) {
return super.equals(other) &&
other instanceof CastToList &&
targetType == ((CastToList) other).targetType &&
allowEmpty == ((CastToList) other).allowEmpty &&
ExpressionTool.equalOrNull(getRetainedStaticContext(), ((CastToList)other).getRetainedStaticContext());
}
/**
* get HashCode for comparing two expressions.
*/
@Override
public int computeHashCode() {
return super.computeHashCode() ^ targetType.hashCode();
}
/**
* Get a name identifying the kind of expression, in terms meaningful to a user.
*
* @return a name identifying the kind of expression, in terms meaningful to a user.
* The name will always be in the form of a lexical XML QName, and should match the name used
* in export() output displaying the expression.
*/
@Override
public String getExpressionName() {
return "castToList";
}
/**
* The toString() method for an expression attempts to give a representation of the expression
* in an XPath-like form, but there is no guarantee that the syntax will actually be true XPath.
* In the case of XSLT instructions, the toString() method gives an abstracted view of the syntax
*/
public String toString() {
return targetType.getEQName() + "(" + getBaseExpression().toString() + ")";
}
@Override
public String toShortString() {
return targetType.getDisplayName() + "(" + getBaseExpression().toShortString() + ")";
}
/**
* Diagnostic print of expression structure. The abstract expression tree
* is written to the supplied output destination.
*/
public void export(ExpressionPresenter out) throws XPathException {
out.startElement("castToList", this);
out.emitAttribute("as", targetType.toString());
getBaseExpression().export(out);
out.endElement();
}
}
// Copyright (c) 2011-2012 Saxonica Limited.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2018 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.expr;
import net.sf.saxon.expr.parser.*;
import net.sf.saxon.lib.ConversionRules;
import net.sf.saxon.om.*;
import net.sf.saxon.trace.ExpressionPresenter;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.type.*;
import net.sf.saxon.value.*;
/**
* Expression class for a cast to a union type
*/
public class CastToUnion extends UnaryExpression {
private UnionType targetType;
private boolean allowEmpty;
/**
* Create a cast expression to a union type
* @param source the operand of the cast
* @param targetType the union type that is the result of the cast
* @param allowEmpty true if an empty sequence may be supplied as input, converting to an empty sequence on output
*/
public CastToUnion(Expression source, UnionType targetType, boolean allowEmpty) {
super(source);
this.targetType = targetType;
this.allowEmpty = allowEmpty;
}
/**
* Get the usage (in terms of streamability analysis) of the single operand
* @return the operand usage
*/
protected OperandRole getOperandRole() {
return OperandRole.SINGLE_ATOMIC;
}
/**
* Ask whether the value of the operand is allowed to be empty
* @return true if an empty sequence may be supplied as input, converting to an empty sequence on output
*/
public boolean isAllowEmpty() {
return allowEmpty;
}
/**
* Get the union type that is the target of this cast operation
* @return the target type of the cast
*/
public UnionType getTargetType() {
return targetType;
}
/**
* Get the namespace resolver that will be used to resolve any namespace-sensitive values (such as QNames) when casting
* @return the namespace resolver, or null if there is none.
*/
public NamespaceResolver getNamespaceResolver() {
return getRetainedStaticContext();
}
/**
* Type-check the expression
*/
/*@NotNull*/
public Expression typeCheck(ExpressionVisitor visitor, ContextItemStaticInfo contextInfo) throws XPathException {
getOperand().typeCheck(visitor, contextInfo);
SequenceType atomicType = SequenceType.makeSequenceType(BuiltInAtomicType.ANY_ATOMIC, getCardinality());
RoleDiagnostic role = new RoleDiagnostic(RoleDiagnostic.TYPE_OP, "cast as", 0);
Expression operand = visitor.getConfiguration().getTypeChecker(false).staticTypeCheck(
getBaseExpression(), atomicType, role, visitor);
setBaseExpression(operand);
if (operand instanceof Literal) {
GroundedValue literalOperand = ((Literal) operand).getValue();
if (literalOperand instanceof AtomicValue) {
GroundedValue<?> av = ((SequenceIterator<?>) iterate(visitor.getStaticContext().makeEarlyEvaluationContext())).materialize();
return Literal.makeLiteral(av, this);
}
if (literalOperand.getLength() == 0) {
if (allowEmpty) {
return operand;
} else {
XPathException err = new XPathException("Cast can never succeed: the operand must not be an empty sequence");
err.setErrorCode("XPTY0004");
err.setLocation(getLocation());
err.setIsTypeError(true);
throw err;
}
}
}
return this;
}
/**
* Perform optimisation of an expression and its subexpressions.
* <p>This method is called after all references to functions and variables have been resolved
* to the declaration of the function or variable, and after all type checking has been done.</p>
*
* @param visitor an expression visitor
* @param contextInfo the static type of "." at the point where this expression is invoked.
* The parameter is set to null if it is known statically that the context item will be undefined.
* If the type of the context item is not known statically, the argument is set to
* {@link net.sf.saxon.type.Type#ITEM_TYPE}
* @return the original expression, rewritten if appropriate to optimize execution
* @throws net.sf.saxon.trans.XPathException
* if an error is discovered during this phase
* (typically a type error)
*/
/*@NotNull*/
public Expression optimize(ExpressionVisitor visitor, ContextItemStaticInfo contextInfo) throws XPathException {
Expression e2 = super.optimize(visitor, contextInfo);
if (e2 != this) {
return e2;
}
// if the operand can't be empty, then set allowEmpty to false to provide more information for analysis
if (!Cardinality.allowsZero(getBaseExpression().getCardinality())) {
allowEmpty = false;
resetLocalStaticProperties();
}
return this;
}
/**
* Get the static cardinality of the expression
*/
public int computeCardinality() {
int c = StaticProperty.ALLOWS_ONE;
if (allowEmpty && Cardinality.allowsZero(getBaseExpression().getCardinality())) {
c |= StaticProperty.ALLOWS_ZERO;
}
try {
if (targetType.containsListType()) {
c |= StaticProperty.ALLOWS_ZERO;
c |= StaticProperty.ALLOWS_MANY;
}
} catch (MissingComponentException e) {
c |= StaticProperty.ALLOWS_ZERO;
c |= StaticProperty.ALLOWS_MANY;
}
return c;
}
/**
* Get the static type of the expression
*/
/*@NotNull*/
public ItemType getItemType() {
if (targetType instanceof PlainType) {
return targetType;
}
return BuiltInAtomicType.ANY_ATOMIC;
}
/**
* Get the static type of the expression as a UType, following precisely the type
* inference rules defined in the XSLT 3.0 specification.
*
* @return the static item type of the expression according to the XSLT 3.0 defined rules
* @param contextItemType
*/
@Override
public UType getStaticUType(UType contextItemType) {
return targetType.getUType();
}
/**
* Determine the special properties of this expression
*
* @return {@link StaticProperty#NO_NODES_NEWLY_CREATED}.
*/
public int computeSpecialProperties() {
int p = super.computeSpecialProperties();
return p | StaticProperty.NO_NODES_NEWLY_CREATED;
}
/**
* Get the expression's dependencies. If the target type is namespace-sensitive, then the expression
* has a dependency on the namespace bindings in the static context
*
* @return the expression's dependencies.
*/
@Override
public int getIntrinsicDependencies() {
return getTargetType().isNamespaceSensitive() ? StaticProperty.DEPENDS_ON_STATIC_CONTEXT : 0;
}
/**
* Copy an expression. This makes a deep copy.
*
* @return the copy of the original expression
* @param rebindings
*/
/*@NotNull*/
public Expression copy(RebindingMap rebindings) {
CastToUnion c = new CastToUnion(getBaseExpression().copy(rebindings), targetType, allowEmpty);
ExpressionTool.copyLocationInfo(this, c);
c.setRetainedStaticContext(getRetainedStaticContext());
return c;
}
/**
* An implementation of Expression must provide at least one of the methods evaluateItem(), iterate(), or process().
* This method indicates which of these methods is provided directly. The other methods will always be available
* indirectly, using an implementation that relies on one of the other methods.
*
* @return the implementation method, for example {@link #ITERATE_METHOD} or {@link #EVALUATE_METHOD} or
* {@link #PROCESS_METHOD}
*/
@Override
public int getImplementationMethod() {
return ITERATE_METHOD;
}
/**
* Evaluate the expression
*/
public SequenceIterator<?> iterate(XPathContext context) throws XPathException {
ConversionRules rules = context.getConfiguration().getConversionRules();
AtomicValue value = (AtomicValue) getBaseExpression().evaluateItem(context);
if (value == null) {
if (allowEmpty) {
return null;
} else {
XPathException e = new XPathException("Cast does not allow an empty sequence");
e.setXPathContext(context);
e.setLocation(getLocation());
e.setErrorCode("XPTY0004");
throw e;
}
}
try {
AtomicSequence result = cast(value, targetType, getRetainedStaticContext(), rules);
return result.iterate();
} catch (XPathException err) {
err.maybeSetContext(context);
err.maybeSetLocation(getLocation());
err.setErrorCode("FORG0001");
throw err;
}
}
/**
* Static method to perform the castable check of an atomic value to a union type
*
* @param value the input value to be converted. Must not be null.
* @param targetType the union type to which the value is to be converted
* @param nsResolver the namespace context, required if the type is namespace-sensitive
* @param context the XPath dynamic evaluation context
* @return the result of the conversion (may be a sequence if the union includes list types in its membership)
*/
public static boolean castable(AtomicValue value, UnionType targetType,
NamespaceResolver nsResolver, XPathContext context) {
try {
CastToUnion.cast(value, targetType, nsResolver, context.getConfiguration().getConversionRules());
return true;
} catch (XPathException err) {
return false;
}
}
/**
* Static method to perform the cast of an atomic value to a union type
*
* @param value the input value to be converted. Must not be null.
* @param targetType the union type to which the value is to be converted
* @param nsResolver the namespace context, required if the type is namespace-sensitive
* @param rules the conversion rules
* @return the result of the conversion (may be a sequence if the union includes list types in its membership)
* @throws XPathException if the conversion fails
*/
public static AtomicSequence cast(AtomicValue value, UnionType targetType,
NamespaceResolver nsResolver, ConversionRules rules)
throws XPathException {
//ConversionRules rules = context.getConfiguration().getConversionRules();
if (value == null) {
throw new NullPointerException();
}
// 1. If the value is a string or untypedAtomic, try casting to each of the member types
if (value instanceof StringValue && !(value instanceof AnyURIValue)) {
try {
return targetType.getTypedValue(value.getStringValueCS(), nsResolver, rules);
} catch (ValidationException e) {
e.setErrorCode("FORG0001");
throw e;
}
}
// 2. If the value is an instance of a type in the transitive membership of the union, return it unchanged
AtomicType label = value.getItemType();
Iterable<PlainType> memberTypes = targetType.getPlainMemberTypes();
// 2a. Is the type annotation itself a member type of the union?
for (PlainType member : memberTypes) {
if (label.equals(member)) {
return value;
}
}
// 2b. Failing that, is some supertype of the type annotation a member type of the union?
for (PlainType member : memberTypes) {
AtomicType t = label;
while (t != null) {
if (t.equals(member)) {
return value;
} else {
t = t.getBaseType() instanceof AtomicType ? (AtomicType) t.getBaseType() : null;
}
}
}
// 3. if the value can be cast to any of the member types, return the result of that cast
for (PlainType type : memberTypes) {
if (type instanceof AtomicType) {
Converter c = rules.getConverter(value.getItemType(), (AtomicType) type);
if (c != null) {
ConversionResult result = c.convert(value);
if (result instanceof AtomicValue) {
return (AtomicValue) result;
}
}
}
}
throw new XPathException("Cannot convert the supplied value to " + targetType.getDescription(), "FORG0001");
}
public String getExpressionName() {
return "castToUnion";
}
/**
* Is this expression the same as another expression?
*/
public boolean equals(Object other) {
return super.equals(other) &&
other instanceof CastToUnion &&
targetType == ((CastToUnion) other).targetType &&
allowEmpty == ((CastToUnion) other).allowEmpty &&
ExpressionTool.equalOrNull(getRetainedStaticContext(), ((CastToUnion) other).getRetainedStaticContext());
}
/**
* get HashCode for comparing two expressions.
*/
@Override
public int computeHashCode() {
return super.computeHashCode() ^ targetType.hashCode();
}
/**
* The toString() method for an expression attempts to give a representation of the expression
* in an XPath-like form, but there is no guarantee that the syntax will actually be true XPath.
* In the case of XSLT instructions, the toString() method gives an abstracted view of the syntax
*/
public String toString() {
return targetType.getEQName() + "(" + getBaseExpression().toString() + ")";
}
/**
* Diagnostic print of expression structure. The abstract expression tree
* is written to the supplied output destination.
*/
public void export(ExpressionPresenter out) throws XPathException {
out.startElement("castToUnion", this);
out.emitAttribute("as", targetType.toExportString());
getBaseExpression().export(out);
out.endElement();
}
}
// Copyright (c) 2011 Saxonica Limited.