java - XML 文档的索引路径

标签 java xpath conceptual

我有一个用于索引 Xpath 的算法,以便我可以通过为 xpath 节点分配唯一索引来处理具有相同 Xpath 但不同值的多个文件。

示例:

文件1:

<Return>
  <ReturnData>
    <Person>
      <Name>Yohanna</Name>
    </Person>
  </ReturnData>
</Return>

文件2:

<Return>
  <ReturnData>
    <Person>
      <Name>Jacoub</Name>
    </Person>
  </ReturnData>
</Return>

所需输出:

1. /Return/ReturnData/Person[1]/Name=Yohanna
2. /Return/ReturnData/Person[2]/Name=Jacoub

我当前的实现给出的输出为:

1. /Return/ReturnData[1]/Person[1]/Name[1]=Yohanna
2. /Return/ReturnData[1]/Person[2]/Name[1]=Jacoub

我想删除 [1],因为不需要它们来表示该节点仅出现 1 次。

索引代码:

public String getFullXPath(Node n) {
    if (null == n) return null;

    Node parent;
    Stack<Node> hierarchy = new Stack<Node>();
    StringBuilder builder = new StringBuilder();

    hierarchy.push(n);

    switch (n.getNodeType()) {
        case Node.ATTRIBUTE_NODE:
            parent = ((Attr) n).getOwnerElement();
            break;
        case Node.ELEMENT_NODE:
            parent = n.getParentNode();
            break;
        case Node.DOCUMENT_NODE:
            parent = n.getParentNode();
            break;
        default:
            throw new IllegalStateException("Unexpected Node type" + n.getNodeType());
    }

    while (null != parent
            && parent.getNodeType() != Node.DOCUMENT_NODE
            && !parent.getNodeName().equals("section")) {

        hierarchy.push(parent);
        parent = parent.getParentNode();
    }

    Object obj;
    while (!hierarchy.isEmpty() && null != (obj = hierarchy.pop())) {
        Node node = (Node) obj;

        if (node.getNodeType() == Node.ELEMENT_NODE) { 
            builder.append("/").append(node.getNodeName());

            int prev_siblings = 1;
            Node prev_sibling = node.getPreviousSibling();
            while (null != prev_sibling) {
                if (prev_sibling.getNodeType() == node.getNodeType()) {
                    if (prev_sibling.getNodeName().equalsIgnoreCase(node.getNodeName())) {
                        prev_siblings++;
                    }
                }
                prev_sibling = prev_sibling.getPreviousSibling();
            }
            // Here is where I say don't append the number of prev_siblings if it equals 1 or the next sibling does not exist
            if(prev_siblings == 1 && node.getNextSibling() == null) {
            } 
            else 
                builder.append("[").append(prev_siblings).append("]");
        } 

        else if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
            builder.append("/@");
            builder.append(node.getNodeName());
        }
    }

    return builder.toString();
}

我已经尝试修复这个问题,但经过三天的研究和调试后我仍然无法解决...不知道...我知道我错过了一些东西,一些我没有看到的东西。任何帮助或帮助将不胜感激。

编辑:

添加了 2 个辅助方法:

private static boolean hasNextElementsWithName(Node node) {
    while (null != node) {
        // checks if next sibling exists
        if(node.getNextSibling().hasAttributes()) {
            return true;
        }
    }
    return false;
}


private static int countPrevElementsWithName(Node node, int prev_siblings,
        Node prev_sibling) {
    while (null != prev_sibling) {

        if (prev_sibling.getNodeType() == node.getNodeType()) {
            if (prev_sibling.getNodeName().equalsIgnoreCase(node.getNodeName())) { 
                prev_siblings++;
            }
        }
        prev_sibling = prev_sibling.getPreviousSibling();

    }
    return prev_siblings;
}

调用方法:

    Object obj;
    while (!hierarchy.isEmpty() && null != (obj = hierarchy.pop())) {
        Node node = (Node) obj;

        if (node.getNodeType() == Node.ELEMENT_NODE) { 
            builder.append("/").append(node.getNodeName());

            int prev_siblings = 1;
            Node prev_sibling = node.getPreviousSibling();

            prev_siblings = countPrevElementsWithName(node, prev_siblings,
                    prev_sibling);


             //@Andreas
            int count = countPrevElementsWithName(node, prev_siblings, prev_sibling);
            if(count != 0 || hasNextElementsWithName(node)) {
                builder.append("[").append(count+1).append("]");
            }

        } 

        else if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
            builder.append("/@");
            builder.append(node.getNodeName());
        }
    }

我现在不知道如何使用它们?

最佳答案

代码 stub

int count = countPrevElementsWithSameName(node);
if (count != 0 || hasNextElementWithSameName(node))
    builder.append("[").append(count + 1).append("]");

辅助方法

private static final boolean hasNextElementWithSameName(Node node) {
    String name = node.getNodeName();
    for (Node next = node.getNextSibling(); next != null; next = next.getNextSibling())
        if (next.getNodeType() == Node.ELEMENT_NODE) // only look at elements
            return next.getNodeName().equals(name); // stop on first element after "node"
    return false;
}
private static final int countPrevElementsWithSameName(Node node) {
    String name = node.getNodeName();
    int count = 0;
    for (Node prev = node.getPreviousSibling(); prev != null; prev = prev.getPreviousSibling())
        if (prev.getNodeType() == Node.ELEMENT_NODE) { // only look at elements
            if (! prev.getNodeName().equals(name))
                break; // stop when element name changes
            count++; // count elements of same name as "node"
        }
    return count;
}

关于java - XML 文档的索引路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32320867/

相关文章:

java - JSP IE6检测

python使用lxml和xpath解析html表上的特定数据

Django:使用 View 来处理模板标签的逻辑?

java - 在 Android Widget 中显示一个变量

java - Windows - 在Java程序中使用set和echo

c# - XPath 选择特定的子元素

java - 未应用last()

cocoa - 在核心数据文档中存储文档特定设置的最佳方法是什么?

.net - .net中实现多线程的不同方式是什么?

java - 设计时间: How to assign to multiple Swing Controls the same event?