要在撒克逊语中对查询进行排序,我们首先运行查询:
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()) {
在两个hasNext()调用中都返回false。
第一个问题,这是做这件事的野兽方法吗?如果没有,什么是更好的方法?
第二个问题,如果这是最好的方法,为什么迭代器会返回hasNext()的假值?
答案 0 :(得分:0)
为什么不使用XQuery进行排序?生成并编译查询
'declare variable $nodes external;
for $n in $nodes order by $n/' + sortkey + ' return $n'
然后编译并执行此查询,将$nodes
绑定到从第一个查询获得的nodeSet
。
我认为您的代码失败的原因是元素位于名称空间中,并且当您构造一个QName来保存排序键时,您正在构造一个无命名空间的QName。