Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,23 @@
import net.sf.saxon.type.BuiltInAtomicType;
import org.exist.dom.QName;
import org.exist.dom.memtree.DocumentImpl;
import org.exist.dom.persistent.NodeProxy;
import org.exist.xquery.ErrorCodes;
import org.exist.xquery.XPathException;
import org.exist.xquery.functions.array.ArrayType;
import org.exist.xquery.functions.fn.FnTransform;
import org.exist.xquery.functions.map.AbstractMapType;
import org.exist.xquery.value.*;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

import io.lacuna.bifurcan.IEntry;

import javax.xml.transform.dom.DOMSource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* Type conversion to and from Saxon
Expand Down Expand Up @@ -119,11 +125,18 @@ static net.sf.saxon.s9api.QName of(final QNameValue qName) {
}

XdmValue of(final Item item) throws XPathException {
if (item instanceof NodeProxy) {
return ofNode(((NodeProxy) item).getNode());
}
final int itemType = item.getType();
if (Type.subTypeOf(itemType, Type.ATOMIC)) {
return ofAtomic((AtomicValue) item);
} else if (Type.subTypeOf(itemType, Type.NODE)) {
return ofNode((Node) item);
} else if (Type.subTypeOf(itemType, Type.MAP)) {
return ofMap((AbstractMapType) item);
} else if (Type.subTypeOf(itemType, Type.ARRAY)) {
return ofArray((ArrayType) item);
}
throw new XPathException(ErrorCodes.XPTY0004,
"Item " + item + " of type " + Type.getTypeName(itemType) + COULD_NOT_BE_CONVERTED + "XdmValue");
Expand All @@ -140,14 +153,12 @@ static private XdmValue ofAtomic(final AtomicValue atomicValue) throws XPathExce
} else if (Type.subTypeOf(itemType, Type.STRING)) {
return XdmValue.makeValue(((StringValue) atomicValue).getStringValue());
}

throw new XPathException(ErrorCodes.XPTY0004,
"Atomic value " + atomicValue + " of type " + Type.getTypeName(itemType) +
COULD_NOT_BE_CONVERTED + "XdmValue");
}

private XdmValue ofNode(final Node node) throws XPathException {

final DocumentBuilder sourceBuilder = newDocumentBuilder();
try {
if (node instanceof DocumentImpl) {
Expand All @@ -167,6 +178,25 @@ private XdmValue ofNode(final Node node) throws XPathException {
}
}

private XdmValue ofMap(final AbstractMapType map) throws XPathException {
Map<XdmAtomicValue, XdmValue> xdmMap = new HashMap<XdmAtomicValue, XdmValue>();
for (IEntry<AtomicValue, Sequence> entry : map) {
XdmAtomicValue key = (XdmAtomicValue) ofAtomic(entry.key());
XdmValue value = of(entry.value());
xdmMap.put(key, value);
}
return new XdmMap(xdmMap);
}

private XdmValue ofArray(final ArrayType array) throws XPathException {
int size = array.getSize();
XdmValue[] members = new XdmValue[size];
for (int i = 0; i < size; ++i) {
members[i] = of(array.get(i));
}
return new XdmArray(members);
}

XdmValue[] of(final ArrayType values) throws XPathException {
final int size = values.getSize();
final XdmValue[] result = new XdmValue[size];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,10 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro
final Transform.TemplateInvocation invocation = new Transform.TemplateInvocation(
options, sourceNode, delivery, xslt30Transformer, resultDocuments);
return invocation.invoke();
} catch (final SaxonApiException | UncheckedXPathException e) {
throw originalXPathException("Could not transform input: ", e, ErrorCodes.FOXT0003);
} catch (final SaxonApiException e) {
throw originalXPathException("Could not transform with "+options.xsltSource._1+" line "+e.getLineNumber()+": ", e, ErrorCodes.FOXT0003);
} catch (final UncheckedXPathException e) {
throw originalXPathException("Could not transform with "+options.xsltSource._1+" line "+e.getXPathException().getLocationAsString()+": ", e, ErrorCodes.FOXT0003);
}

} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

import net.sf.saxon.s9api.XdmNode;
import org.exist.xquery.value.NodeValue;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

Expand Down Expand Up @@ -64,20 +65,41 @@ static StringBuilder pathTo(final Node node) {
static List<Integer> treeIndex(final Node node) {
final Node parent = node.getParentNode();
if (parent == null) {
return new ArrayList<>();
final List<Integer> index = new ArrayList<>();
// The root element always index 0 within the document node.
// Some node implementations (e.g., org.exist.dom.memtree.NodeImpl) do not always have an associated document.
// In this case, the nodeIndex must get an extra 0 index to be valid for xdmDocument.
if (! (node instanceof Document)) {
index.add(0);
}
return index;
}
final List<Integer> index = treeIndex(parent);
Node sibling = node.getPreviousSibling();
Node sibling = previousSiblingNotAttribute(node);
int position = 0;
while (sibling != null) {
position += 1;
sibling = sibling.getPreviousSibling();
sibling = previousSiblingNotAttribute(sibling);
}
index.add(position);

return index;
}

/**
* A org.exist.dom.persistent.StoredNode returns attributes of an element as previous siblings of the element's children.
* This is not compatible with the way xdmNodeAtIndex works, so we need to compensate for this.
* @param node
* @return the previous sibling of `node` that is not an attribute.
*/
private static Node previousSiblingNotAttribute(Node node) {
Node sibling = node.getPreviousSibling();
if (sibling instanceof Attr) {
return null;
}
return sibling;
}

static XdmNode xdmNodeAtIndex(final XdmNode xdmNode, final List<Integer> index) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this method not be adapted? This loops over children(), are these not including attributes?

if (index.isEmpty()) {
return xdmNode;
Expand Down
Loading