Чтобы отсортировать запрос в Saxon, мы сначала запускаем запрос:
XPathExecutable exe = xPath.compile(query);
XPathSelector selector = exe.load();
selector.setContextItem(xmlDocument);
XdmValue nodeSet = selector.evaluate();
// put the results in an array
ArrayList<XdmItem> nodes = new ArrayList<XdmItem>();
for (int i = 0; i < nodeSet.size(); i++)
nodes.add(nodeSet.itemAt(i));
// Sort the results
sortNodes(nodes, "RiskLevel", false, false);
private void sortNodes(ArrayList<XdmItem> nodes, final String sortKey, final boolean sortIsAttr, boolean descending) {
Comparator comparator = new Comparator() {
public int compare(Object node1, Object node2) {
if (node1 instanceof XdmNode && node2 instanceof XdmNode) {
if (sortIsAttr) {
return ((XdmNode) node1).getAttributeValue(new QName(sortKey)).compareTo(((XdmNode) node2).getAttributeValue(new QName(sortKey)));
}
else {
XdmSequenceIterator iter1, iter2;
if (sortKey.equals(".")) {
iter1 = ((XdmNode) node1).axisIterator(Axis.SELF, new QName(((XdmNode) node1).getNodeName().getLocalName()));
iter2 = ((XdmNode) node2).axisIterator(Axis.SELF, new QName(((XdmNode) node2).getNodeName().getLocalName()));
} else if (sortKey.contains("/")){
// we get here when the sortKey is a descendant, but not direct child of the node, so we traverse down the tree to get there
String key = sortKey;
while (key.contains("/")) {
node1 = ((XdmNode) node1).axisIterator(Axis.CHILD, new QName(key.substring(0, key.indexOf("/")))).next();
node2 = ((XdmNode) node2).axisIterator(Axis.CHILD, new QName(key.substring(0, key.indexOf("/")))).next();
key = key.substring(key.indexOf("/") + 1);
}
iter1 = ((XdmNode) node1).axisIterator(Axis.CHILD, new QName(key));
iter2 = ((XdmNode) node2).axisIterator(Axis.CHILD, new QName(key));
} else {
iter1 = ((XdmNode) node1).axisIterator(Axis.CHILD, new QName(sortKey));
iter2 = ((XdmNode) node2).axisIterator(Axis.CHILD, new QName(sortKey));
}
if(iter1.hasNext() && iter2.hasNext()) {
String val1 = iter1.next().getStringValue();
String val2 = iter2.next().getStringValue();
if(parseableAsDouble(val1) && parseableAsDouble(val2)) {
Double val1Double = Double.parseDouble(val1);
Double val2Double = Double.parseDouble(val2);
return val1Double.compareTo(val2Double);
}
Date val1Date = parseAsDate(val1);
Date val2Date = parseAsDate(val2);
if(val1Date != null && val2 != null)
return val1Date.compareTo(val2Date);
return (val1.compareTo(val2));
}
return 0;
}
} else {
assert node1 != null && node2 != null;
return ((XdmItem)node1).getStringValue().compareTo(((XdmItem) node2).getStringValue());
}
}
};
if (descending)
comparator = Collections.reverseOrder(comparator);
Collections.sort(nodes, comparator);
}
Проблема заключается в следующем XML (nodeSet.toString ():
<Securities xmlns="http://www.windward.net">
<RiskLevel>4</RiskLevel>
Код:
iter1 = ((XdmNode) node1).axisIterator(Axis.CHILD, new QName(sortKey));
iter2 = ((XdmNode) node2).axisIterator(Axis.CHILD, new QName(sortKey));
}
if(iter1.hasNext() && iter2.hasNext()) {
возвращает false при обоих вызовах hasNext ().
Первый вопрос: это лучший способ сделать это? Если нет, то какой подход лучше?
Второй вопрос, если это лучший способ, почему итераторы возвращают false ofr hasNext ()?