【问题标题】:Trying to sort a node set from Saxon试图对撒克逊的节点集进行排序
【发布时间】:2019-02-17 23:34:01
【问题描述】:

要在 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()) {

两次 hasNext() 调用都返回 false。

第一个问题,这是执行此操作的最佳方式吗?如果没有,有什么更好的方法?

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

【问题讨论】:

    标签: java saxon


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 能否以Java 代码的形式提供解决方案?我需要返回一个可以迭代的节点列表。我有类似“/root/node1/node2 order by node 3”之类的东西,调用应用程序向我传递了一个查询。我可以打破、重组查询,但我需要知道如何获取作为查询结果的 XdmItem 对象列表。 TIA。
    • 想通了——当我需要 XQueryCompiler 时,我仍在尝试使用 XPathCompiler。
    猜你喜欢
    • 2014-03-30
    • 2016-01-25
    • 1970-01-01
    • 2010-10-02
    • 1970-01-01
    • 1970-01-01
    • 2013-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多