Получение Xpath всех узлов в xml

#java #dom #xpath

#java #dom #xpath

Вопрос:

У меня есть xml. Я хочу получить / распечатать Xpath (полный) всех узлов в нем, используя Java. Я пытаюсь использовать анализатор DOM.

 File stocks = new File("File Name");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); 
Document doc = dBuilder.parse(stocks); 
System.out.println("Parsed successfully"); 
doc.getDocumentElement();        
System.out.println("root of xml file : "   doc.getDocumentElement().getNodeName());
 

Я могу заставить свой корневой узел печатать, но не его дочерние элементы.

Комментарии:

1. Я не уверен, почему это было отклонено.

Ответ №1:

Как ни странно, я только что написал метод, который можно было бы использовать для этого. Однако это не полностью учитывает пространство имен, поэтому имейте в виду, что оно также работает только для типов ЭЛЕМЕНТОВ.


Чтобы этот метод работал, вам также необходимо, чтобы ваш документ знал пространство имен. dbFactory.setNamespaceAware(true); . Если вы не можете использовать это пространство имен, тогда замените его везде, где увидите getLocalName() getTagName() .


 try {
    XPath xpath = XPathFactory.newInstance().newXPath();
    // get all nodes in the document
    NodeList nList = (NodeList) xpath.evaluate("//*", doc.getDocumentElement() ,XPathConstants.NODESET);

    for(int i=0;i<nList.getLength();i  ) {
        if(nList.item(i).getNodeType() == Node.ELEMENT_NODE)
            System.out.println(getElementXPath((Element)nList.item(i), doc.getDocumentElement()));
    }
} catch (XPathExpressionException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}


 /**
 * Finds the xPath relative to the given node, the relativeTo should always be a parent of elt
 * @param elt 
 * @param relativeTo should be a parent of elt, if it isnt the path from the document root will be returned
 * @return
 */
public static String getElementXPath(Element elt, Element relativeTo) {
    String path = ""; 

    do {
        String xname = elt.getLocalName()   "["   getElementIndex(elt)   "]";
        path = "/"   xname   path;

        if(elt.getParentNode() != null amp;amp; elt.getParentNode().getNodeType() == Element.ELEMENT_NODE)
            elt = (Element) elt.getParentNode();
        else
            elt = null;
    } while(elt != null amp;amp; !elt.equals(relativeTo));

    return path;                            
}

/**
 * @param original
 * @return the index this element is among its siblings, only accounts for siblings with the same tag name as itself. Used for xpath indexing
 */
private static int getElementIndex(Element original) {
    int count = 1;

    for (Node node = original.getPreviousSibling(); node != null; node = node.getPreviousSibling()) {
        if (node.getNodeType() == Node.ELEMENT_NODE) {
            Element element = (Element) node;
            if (element.getLocalName().equals(original.getLocalName()) amp;amp; 
                    (element.getNamespaceURI() == original.getNamespaceURI() || (element.getNamespaceURI() != null amp;amp; element.getNamespaceURI().equals(original.getNamespaceURI())))) {
                count  ;
            }
        }
    }

    return count;
}