Skip to content

Commit

Permalink
feat: update Saxon library to v11.4
Browse files Browse the repository at this point in the history
This commit updates the Saxon-HE dependency to version 11.4.

It refactors the Saxon-related code as follows:
- update the function+registration code to the latest API changes
- extract the Saxon schema reader factory (used by Jing) in its own class
- the Saxon schema reader factory is made available to Jing via the SPI
  mechanism (declared in
  `META-INF/services/com.thaiopensource.validate.SchemaReaderFactory`).
  This notably allows Jing to find and use our factory for both Schematron
  and NVDL.
- the Saxon schema reader factory no longer extends Jing's
  `NewSaxonSchemaReaderFactory`, which set the feature "XSLT_VERSION"
  to "2.0" and caused a Warning to be issued by Saxon 11.

Fix #1341
  • Loading branch information
rdeltour committed Dec 9, 2022
1 parent 3d25330 commit ef2697e
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 104 deletions.
6 changes: 3 additions & 3 deletions pom.xml
Expand Up @@ -178,7 +178,7 @@
<dependency>
<groupId>net.sf.saxon</groupId>
<artifactId>Saxon-HE</artifactId>
<version>9.8.0-8</version>
<version>11.4</version>
</dependency>
<dependency>
<groupId>nu.validator</groupId>
Expand Down Expand Up @@ -368,7 +368,7 @@
<configuration>
<instructions>
<Import-Package>
net.sf.saxon.*;version="[9.8.0,9.8.1)",
net.sf.saxon.*;version="[11.4.0,11.4.1)",
*
</Import-Package>
<Automatic-Module-Name>org.w3c.epubcheck</Automatic-Module-Name>
Expand Down Expand Up @@ -444,7 +444,7 @@
<dependency>
<groupId>net.sf.saxon</groupId>
<artifactId>Saxon-HE</artifactId>
<version>9.4</version>
<version>11.4</version>
</dependency>
</dependencies>
</plugin>
Expand Down
106 changes: 26 additions & 80 deletions src/main/java/com/adobe/epubcheck/xml/XMLValidator.java
Expand Up @@ -28,11 +28,6 @@
import java.net.URISyntaxException;
import java.net.URL;

import javax.xml.transform.TransformerFactory;

import org.idpf.epubcheck.util.saxon.ColumnNumberFunction;
import org.idpf.epubcheck.util.saxon.LineNumberFunction;
import org.idpf.epubcheck.util.saxon.SystemIdFunction;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
Expand All @@ -48,16 +43,7 @@
import com.thaiopensource.validate.SchemaReader;
import com.thaiopensource.validate.ValidateProperty;
import com.thaiopensource.validate.auto.AutoSchemaReader;
import com.thaiopensource.validate.auto.SchemaReaderFactorySchemaReceiverFactory;
import com.thaiopensource.validate.rng.CompactSchemaReader;
import com.thaiopensource.validate.schematron.NewSaxonSchemaReaderFactory;

import net.sf.saxon.Configuration;
import net.sf.saxon.TransformerFactoryImpl;
import net.sf.saxon.sxpath.IndependentContext;
import net.sf.saxon.sxpath.XPathStaticContext;
import net.sf.saxon.trans.SymbolicName;


public class XMLValidator
{
Expand All @@ -84,19 +70,19 @@ public static BasicResolver getInstance()
return theInstance;
}

public void resolve(Identifier id, Input input) throws
IOException,
ResolverException
public void resolve(Identifier id, Input input)
throws IOException,
ResolverException
{
if (!input.isResolved())
{
input.setUri(resolveUri(id));
}
}

public void open(Input input) throws
IOException,
ResolverException
public void open(Input input)
throws IOException,
ResolverException
{
if (!input.isUriDefinitive())
{
Expand All @@ -106,8 +92,7 @@ public void open(Input input) throws
try
{
uri = new URI(input.getUri());
}
catch (URISyntaxException e)
} catch (URISyntaxException e)
{
throw new ResolverException(e);
}
Expand All @@ -122,8 +107,8 @@ public void open(Input input) throws
input.setByteStream(url.openStream());
}

public static String resolveUri(Identifier id) throws
ResolverException
public static String resolveUri(Identifier id)
throws ResolverException
{
try
{
Expand Down Expand Up @@ -153,74 +138,40 @@ public static String resolveUri(Identifier id) throws
}

return uriRef;
}
catch (URISyntaxException e)
} catch (URISyntaxException e)
{
throw new ResolverException(e);
}
catch (MalformedURLException e)
} catch (MalformedURLException e)
{
throw new ResolverException(e);
}
}
}

/**
* Extends Jing's Saxon 9 schema reader factory by registering
* extension functions.
*/
static public class ExtendedSaxonSchemaReaderFactory extends NewSaxonSchemaReaderFactory
{
public void initTransformerFactory(TransformerFactory factory)
{
super.initTransformerFactory(factory);
SymbolicName.F lineNumberFn = new SymbolicName.F(LineNumberFunction.QNAME, 0);
SymbolicName.F columnNumberFn = new SymbolicName.F(ColumnNumberFunction.QNAME, 0);
SymbolicName.F systemIdFn = new SymbolicName.F(SystemIdFunction.QNAME, 0);
if (factory instanceof TransformerFactoryImpl)
{
Configuration configuration = ((TransformerFactoryImpl) factory).getConfiguration();
XPathStaticContext xpathContext = new IndependentContext(configuration);
if (!xpathContext.getFunctionLibrary().isAvailable(lineNumberFn))
{
configuration.registerExtensionFunction(new LineNumberFunction());
}
if (!xpathContext.getFunctionLibrary().isAvailable(columnNumberFn))
{
configuration.registerExtensionFunction(new ColumnNumberFunction());
}
if (!xpathContext.getFunctionLibrary().isAvailable(systemIdFn))
{
configuration.registerExtensionFunction(new SystemIdFunction());
}
}
}
}

// handles errors in schemas
private class ErrorHandlerImpl implements ErrorHandler
{

public void error(SAXParseException exception) throws
SAXException
public void error(SAXParseException exception)
throws SAXException
{
exception.printStackTrace();
}

public void fatalError(SAXParseException exception) throws
SAXException
public void fatalError(SAXParseException exception)
throws SAXException
{
exception.printStackTrace();
}

public void warning(SAXParseException exception) throws
SAXException
public void warning(SAXParseException exception)
throws SAXException
{
exception.printStackTrace();
}

}

public XMLValidator(String schemaName, boolean isNormative)
{
this.isNormative = isNormative;
Expand All @@ -245,36 +196,31 @@ public XMLValidator(String schemaName, boolean isNormative)
if (schemaName.endsWith(".rnc"))
{
schemaReader = CompactSchemaReader.getInstance();
} else if (schemaName.endsWith(".sch")) {
schemaReader = new AutoSchemaReader(
new SchemaReaderFactorySchemaReceiverFactory(
new ExtendedSaxonSchemaReaderFactory()));
}
else
{

schemaReader = new AutoSchemaReader();
}

schema = schemaReader.createSchema(schemaSource,
mapBuilder.toPropertyMap());
}
catch (RuntimeException e)
} catch (RuntimeException e)
{
throw e;
}
catch (Exception e)
} catch (Exception e)
{
e.printStackTrace();
throw new Error("Internal error: " + e + " " + schemaName);
}
}

public Schema getSchema() {

public Schema getSchema()
{
return schema;
}

public boolean isNormative() {

public boolean isNormative()
{
return isNormative;
}
}
Expand Up @@ -13,8 +13,6 @@
public class ColumnNumberFunction extends ExtensionFunctionDefinition
{

private static final long serialVersionUID = -4202710868367933385L;

public static StructuredQName QNAME = new StructuredQName("saxon", "http://saxon.sf.net/", "column-number");

@Override
Expand Down Expand Up @@ -64,9 +62,7 @@ public ExtensionFunctionCall makeCallExpression()
{
return new ExtensionFunctionCall()
{
private static final long serialVersionUID = -4202710868367933385L;

public Sequence call(XPathContext context, @SuppressWarnings("rawtypes") Sequence[] arguments) throws XPathException
public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException
{
if (context.getContextItem() instanceof NodeInfo)
{
Expand Down
Expand Up @@ -3,7 +3,6 @@
import net.sf.saxon.om.Item;
import net.sf.saxon.om.Sequence;
import net.sf.saxon.om.SequenceIterator;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.value.Int64Value;

class Int64ValueSequence implements Sequence
Expand All @@ -21,8 +20,7 @@ public Item head()
}

@Override
public SequenceIterator iterate() throws
XPathException
public SequenceIterator iterate()
{
return item.iterate();
}
Expand Down
Expand Up @@ -13,8 +13,6 @@
public class LineNumberFunction extends ExtensionFunctionDefinition
{

private static final long serialVersionUID = -4202710868367933385L;

public static StructuredQName QNAME = new StructuredQName("saxon", "http://saxon.sf.net/", "line-number");

@Override
Expand Down Expand Up @@ -65,9 +63,7 @@ public ExtensionFunctionCall makeCallExpression()
return new ExtensionFunctionCall()
{

private static final long serialVersionUID = -4202710868367933385L;

public Sequence call(XPathContext context, @SuppressWarnings("rawtypes") Sequence[] arguments) throws XPathException
public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException
{
if (context.getContextItem() instanceof NodeInfo)
{
Expand Down
@@ -0,0 +1,55 @@
package org.idpf.epubcheck.util.saxon;

import javax.xml.transform.TransformerFactory;

import com.thaiopensource.validate.schematron.SchematronSchemaReaderFactory;

import net.sf.saxon.Configuration;
import net.sf.saxon.TransformerFactoryImpl;
import net.sf.saxon.lib.ErrorReporter;
import net.sf.saxon.lib.FeatureKeys;
import net.sf.saxon.s9api.XmlProcessingError;
import net.sf.saxon.sxpath.IndependentContext;
import net.sf.saxon.sxpath.XPathStaticContext;
import net.sf.saxon.trans.SymbolicName;

public class SaxonSchemaReaderFactory extends SchematronSchemaReaderFactory
{
public void initTransformerFactory(TransformerFactory factory)
{
super.initTransformerFactory(factory);
factory.setAttribute(FeatureKeys.LINE_NUMBERING, Boolean.TRUE);
SymbolicName.F lineNumberFn = new SymbolicName.F(LineNumberFunction.QNAME, 0);
SymbolicName.F columnNumberFn = new SymbolicName.F(ColumnNumberFunction.QNAME, 0);
SymbolicName.F systemIdFn = new SymbolicName.F(SystemIdFunction.QNAME, 0);
if (factory instanceof TransformerFactoryImpl)
{
Configuration configuration = ((TransformerFactoryImpl) factory).getConfiguration();
configuration.setErrorReporterFactory(config -> {
return new ErrorReporter()
{

@Override
public void report(XmlProcessingError error)
{
System.out.println(error.getMessage());

}
};
});
XPathStaticContext xpathContext = new IndependentContext(configuration);
if (!xpathContext.getFunctionLibrary().isAvailable(lineNumberFn, 20))
{
configuration.registerExtensionFunction(new LineNumberFunction());
}
if (!xpathContext.getFunctionLibrary().isAvailable(columnNumberFn, 20))
{
configuration.registerExtensionFunction(new ColumnNumberFunction());
}
if (!xpathContext.getFunctionLibrary().isAvailable(systemIdFn, 20))
{
configuration.registerExtensionFunction(new SystemIdFunction());
}
}
}
}
Expand Up @@ -5,8 +5,8 @@
import net.sf.saxon.lib.ExtensionFunctionDefinition;
import net.sf.saxon.om.Item;
import net.sf.saxon.om.NodeInfo;
import net.sf.saxon.om.SequenceIterator;
import net.sf.saxon.om.Sequence;
import net.sf.saxon.om.SequenceIterator;
import net.sf.saxon.om.StructuredQName;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.value.AnyURIValue;
Expand All @@ -15,8 +15,6 @@
public class SystemIdFunction extends ExtensionFunctionDefinition
{

private static final long serialVersionUID = -4202710868367933385L;

public static StructuredQName QNAME = new StructuredQName("saxon", "http://saxon.sf.net/", "system-id");

@Override
Expand Down Expand Up @@ -66,9 +64,7 @@ public ExtensionFunctionCall makeCallExpression()
{
return new ExtensionFunctionCall()
{
private static final long serialVersionUID = -4202710868367933385L;

public Sequence call(XPathContext context, @SuppressWarnings("rawtypes") Sequence[] arguments) throws XPathException
public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException
{
if (context.getContextItem() instanceof NodeInfo)
{
Expand All @@ -94,8 +90,7 @@ public Item head()
}

@Override
public SequenceIterator iterate() throws
XPathException
public SequenceIterator iterate()
{
return item.iterate();
}
Expand Down
@@ -0,0 +1 @@
org.idpf.epubcheck.util.saxon.SaxonSchemaReaderFactory

0 comments on commit ef2697e

Please sign in to comment.