Путь индекса для документа XML
У меня есть алгоритм индексации 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();
}
Я пытался исправить это, но я все еще не могу после 3 дней изучения и отладки ... Не знаю ... Я знаю, что что-то упустил, что-то не вижу. Любая помощь или помощь будет высоко ценится.
Редактировать:
Добавлено 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());
}
}
Я не уверен, как их использовать сейчас?