Caminho do índice para documento XML
Eu tenho um algoritmo para indexar um Xpath para que eu possa processar vários arquivos com o mesmo Xpath, mas com valores diferentes, atribuindo um nó exclusivo a um nó xpath.
Exemplo:
Arquivo 1:
<Return>
<ReturnData>
<Person>
<Name>Yohanna</Name>
</Person>
</ReturnData>
</Return>
Arquivo 2:
<Return>
<ReturnData>
<Person>
<Name>Jacoub</Name>
</Person>
</ReturnData>
</Return>
Saída desejada:
1. /Return/ReturnData/Person[1]/Name=Yohanna
2. /Return/ReturnData/Person[2]/Name=Jacoub
Minha implementação atual me fornece uma saída de:
1. /Return/ReturnData[1]/Person[1]/Name[1]=Yohanna
2. /Return/ReturnData[1]/Person[2]/Name[1]=Jacoub
Eu gostaria de remover os [1], pois eles não são necessários para indicar que há apenas 1 ocorrência desse nó.
Código de indexação:
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();
}
Eu tentei consertar isso, mas ainda não consigo depois de três dias analisando e depurando ... Não faço ideia ... sei que estou perdendo alguma coisa, algo que não estou vendo. Qualquer ajuda ou assistência seria muito apreciada.
Editar:
Adicionado 2 métodos auxiliares:
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;
}
Método de chamada:
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());
}
}
Não tenho certeza de como usá-los agora?