有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Saxon XdmNode。“”上的axisIterator()节点

我有一个XdmNode,需要从描述子节点/属性的特定XPath中获取的第一个子节点/属性。因此,我做了以下工作:

XdmSequenceIterator iter1 = ((XdmNode)node1).axisIterator(Axis.CHILD, new QName(subKey));

这适用于除“.”之外的所有子键在这种情况下,iter1。hasNext()返回false

对于这一种情况,我可以执行以下操作:

XdmSequenceIterator iter1 = ((XdmNode)node1).axisIterator(Axis.PARENT, new QName(((XdmNode) node1).getNodeName().getLocalName()));

但这让我觉得可能会在以后的比赛中咬到我

有更好的方法吗

更新:假设我有XPath“/Order/Dates/Date”,并希望按日期顺序恢复节点。因此,我的XPath select将获取节点列表。然后我遍历这些返回的节点,对它们进行排序。对于每个节点,我调用axisIterator()来获取值。该值是该节点的“so”

更新#2: 目前,为了对查询结果进行排序,我们将所有结果读入ArrayList,然后使用compare()方法调用sort,如下所示:

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 = ((XdmNode)node1).axisIterator(Axis.CHILD, new QName(sortKey));
                    XdmSequenceIterator 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 {
                return ((XdmItem)node1).getStringValue().compareTo(((XdmItem) node2).getStringValue());
            }
        }
    };
    if(descending){
        comparator = Collections.reverseOrder(comparator);
    }
    Collections.sort(nodes, comparator);

除非sortKey=“.”,否则上述方法非常有效。那是因为不是节点的子节点,而是节点。因此,要实现这一点,就要解决这一问题,调用((XdmNode)节点1)。axisIterator(Axis.PARENT,新的QName(((XdmNode)节点1)。getNodeName()。getLocalName())

更新#3: 现在我提议的解决办法不起作用了。这很奇怪,因为父节点确实将该节点作为子节点


共 (1) 个答案

  1. # 1 楼答案

    如果sortKey被指定为“.”,您可以使用XdmNode提取两个节点的字符串值。getStringValue(),然后使用与子节点相同的启发式逻辑比较字符串值

    或者,为什么不使用XPath引擎本身来计算排序键,而不是自己尝试解释它呢

    构造一个表达式,比如

    let $x := string(" + subKey + ") 
    return if ($x castable as xs:double) then xs:double($x) 
           else if ($x castable as xs:date) then xs:date($x) 
           else $x
    

    对两个节点进行评估,并使用XdmAtomicValue.getUnderlyingValue().getSchemaComparable().compare()比较结果

    类似这样(未经测试):

    private void sortNodes(ArrayList<XdmItem> nodes, final String sortKey, XPathCompiler xpc, boolean descending) {
        final XPathExpression computeSortKey = xpc.compile(
           "let $x := string('" + sortKey + "') 
            return if ($x castable as xs:double) then xs:double($x) 
            else if ($x castable as xs:date) then xs:date($x) 
            else $x");
        Comparator comparator = new Comparator() {
            public int compare(Object node1, Object node2) {
                if (node1 instanceof XdmNode && node2 instanceof XdmNode)           {
                    XPathSelector selector = computeSortKey.load();
                    selector.setContextItem(((XdmNode)node1);
                    XdmAtomicValue key1 = (XdmAtomicValue)selector.evaluateSingle();
                    selector.setContextItem(((XdmNode)node2);
                    XdmAtomicValue key2 = (XdmAtomicValue)selector.evaluateSingle();
                    return key1.getUnderlyingValue().getSchemaComparable().compare(
                       key2.getUnderlyingValue().getSchemaComparable());
                } else {
                    return ((XdmItem)node1).getStringValue().compareTo(((XdmItem) node2).getStringValue());
                }
            }
        };
        if(descending){
            comparator = Collections.reverseOrder(comparator);
        }
        Collections.sort(nodes, comparator);
    

    然而,我认为最好不要以这种方式混合Java和XPath,而是在一个XQuery表达式中完成整个过程