diff --git a/gradle.properties b/gradle.properties index ba62080..1c38cb1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,6 +2,6 @@ org.gradle.jvmargs=-Xmx4096m basename=sinclude sincludeTitle=Saxon XInclude -sincludeVersion=4.2.0 +sincludeVersion=4.2.1 saxonVersion=11.4 diff --git a/src/main/java/com/nwalsh/sinclude/XInclude.java b/src/main/java/com/nwalsh/sinclude/XInclude.java index 6dce556..aaf77bd 100644 --- a/src/main/java/com/nwalsh/sinclude/XInclude.java +++ b/src/main/java/com/nwalsh/sinclude/XInclude.java @@ -172,6 +172,7 @@ public void expandXIncludes(File input, File output) throws SaxonApiException, X logger = new DebuggingLogger(node.getUnderlyingNode().getConfiguration().getLogger()); TreeWalker walker = new TreeWalker(); + walker.setXmlBase(input.toURI()); walker.register(xi_include, new XiIncludeHandler(this)); walker.register(xi_fallback, new XiFallbackHandler()); @@ -547,6 +548,8 @@ public XdmNode process(XdmNode node) { private class TreeWalker { private HashMap handlers = new HashMap<>(); + private URI overrideBaseURI = null; + private boolean root = true; public void register(QName name, ElementHandler handler) { if (handlers.containsKey(name)) { @@ -555,6 +558,10 @@ public void register(QName name, ElementHandler handler) { handlers.put(name, handler); } + public void setXmlBase(URI base) { + overrideBaseURI = base; + } + public XdmNode walk(XdmNode node) throws XPathException { XdmDestination destination = ReceiverUtils.makeDestination(node); Receiver receiver = ReceiverUtils.makeReceiver(node, destination); @@ -565,7 +572,7 @@ public XdmNode walk(XdmNode node) throws XPathException { return destination.getXdmNode(); } - public void traverse(Receiver receiver, XdmNode node) throws XPathException { + private void traverse(Receiver receiver, XdmNode node) throws XPathException { XdmSequenceIterator iter = null; if (node.getNodeKind() == XdmNodeKind.DOCUMENT) { @@ -584,7 +591,18 @@ public void traverse(Receiver receiver, XdmNode node) throws XPathException { } else { NodeInfo inode = node.getUnderlyingNode(); FingerprintedQName name = new FingerprintedQName(inode.getPrefix(), inode.getURI(), inode.getLocalPart()); - receiver.startElement(name, inode.getSchemaType(), inode.attributes(), inode.getAllNamespaces(), inode.saveLocation(), 0); + + final AttributeMap amap; + if (root && fixupXmlBase && overrideBaseURI != null && inode.getAttributeValue(NS_XML, "base") == null) { + FingerprintedQName xml_base = new FingerprintedQName("xml", NS_XML, "base"); + AttributeInfo base = new AttributeInfo(xml_base, BuiltInAtomicType.ANY_URI, overrideBaseURI.toString(), inode.saveLocation(), 0); + amap = inode.attributes().put(base); + } else { + amap = inode.attributes(); + } + root = false; + + receiver.startElement(name, inode.getSchemaType(), amap, inode.getAllNamespaces(), inode.saveLocation(), 0); iter = node.axisIterator(Axis.CHILD); while (iter.hasNext()) { XdmNode item = iter.next();