Попытка отсортировать набор узлов из саксонской - PullRequest
0 голосов
/ 18 февраля 2019

Чтобы отсортировать запрос в 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 ()?

1 Ответ

0 голосов
/ 18 февраля 2019

Почему вы не используете XQuery для сортировки?Сгенерируйте и скомпилируйте запрос

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

, а затем скомпилируйте и выполните этот запрос, привязав $nodes к вашему nodeSet, полученному из первого запроса.

Я думаю, что причина вашегосбой кода состоит в том, что элементы находятся в пространстве имен, и когда вы создаете QName для хранения ключа сортировки, вы создаете QName без пространства имен.

...