尝试对来自撒克逊的节点集进行排序 [英] Trying to sort a node set from Saxon

查看:46
本文介绍了尝试对来自撒克逊的节点集进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要在 Saxon 中对查询进行排序,我们首先运行查询:

To sort a query in Saxon we first run the query:

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():

The problem is for the following 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.

returns false on both hasNext() calls.

第一个问题,这是做这件事的野兽方式吗?如果没有,什么是更好的方法?

First question, is this the beast way to do this? If not, what is a better approach?

第二个问题,如果这是最好的方法,为什么迭代器返回 false ofr hasNext()?

Second question, if this is the best way, why do the iterators return false ofr hasNext()?

推荐答案

为什么不使用 XQuery 进行排序?生成并编译查询

Why don't you use XQuery to do the sorting? Generate and compile the query

'declare variable $nodes external;
for $n in $nodes order by $n/' + sortkey + ' return $n'

然后编译并执行此查询,将 $nodes 绑定到从第一个查询中获得的 nodeSet.

and then compile and execute this query, binding $nodes to your nodeSet obtained from the first query.

我认为您的代码失败的原因是元素位于命名空间中,并且当您构造一个 QName 来保存排序键时,您正在构造一个无命名空间的 QName.

I would think that the reason your code is failing is that the elements are in a namespace, and when you construct a QName to hold the sort key, you are constructing a no-namespace QName.

这篇关于尝试对来自撒克逊的节点集进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆