I have a piece of code to generate xpath for a node. But it doesn't create array structure of it. For example, if an element has two elements with same name, I need to provide index to point to them appropriately. An illustration of it is below.
我有一段代码为节点生成xpath。但它不会创建它的数组结构。例如,如果一个元素有两个具有相同名称的元素,我需要提供索引以适当地指向它们。它的一个例子在下面。
<abc>
<def>
</hij>
</def>
<def>
</lmn>
</def>
</abc>
Now, to get xpath for hij
, I would need something like this:
现在,为了得到hij的xpath,我需要这样的东西:
//abc[1]/def[1]/hij
To get xpath for lmn
, I would need something like this:
要获得lmn的xpath,我需要这样的东西:
//abc[1]/def[2]/lmn
I have a piece of code which will simply give me //abc/def/hij
and //abc/def/lmn
我有一段代码只会给我// abc / def / hij和// abc / def / lmn
private String getXPath(Node root, String elementName)
{
for (int i = 0; i < root.getChildNodes().getLength(); i++)
{
Node node = root.getChildNodes().item(i);
if (node instanceof Element)
{
if (node.getNodeName().equals(elementName))
{
return "\\" + node.getNodeName();
}
else if (node.getChildNodes().getLength() > 0)
{
if(map.containsKey(node.getNodeName()))
map.put(node.getNodeName(), map.get(node.getNodeName())+1);
else
map.put(node.getNodeName(), 1);
this.xpath = getXPath(node, elementName);
if (this.xpath != null){
return "\\" + node.getNodeName() +"["+map.get(node.getNodeName())+"]"+ this.xpath;
}
}
}
}
return null;
}
Can someone help me to append array structure with this?
有人可以帮我添加数组结构吗?
2 个解决方案
#1
0
<abc>
<def>
</hij>
</def>
<def>
</lmn>
</def>
</abc>
In here. You are closing
在这里。你正在结束
</hij>
and
</lmn>
without opening them. If you are opening them before abc, them you can't close them inside abc. Basically: You can't intertwince them. Open one, open second, close second, close one. Never in another way around.
没有打开它们。如果你在abc之前打开它们,你就无法在abc中关闭它们。基本上:你不能交织他们。打开一个,打开第二个,关闭第二个,关闭一个。从来没有以另一种方式。
This might lead to your error
这可能会导致您的错误
#2
0
I'm unable to fix your code in the question as it is not complete, for example where is map defined? Also see other answer about your malformed input.
我无法在问题中修复您的代码,因为它不完整,例如地图定义在哪里?另请参阅有关您的格式错误输入的其他答案。
Making the assumption that hij and lmn should have been short tags, here is a complete solution.
假设hij和lmn应该是短标签,这是一个完整的解决方案。
- I used the approach of navigating up the tree using getParentNode().
- I've included XPath tests to check that the generated expression returns the same node
- Extended input to contain elements of different names at the same level.
我使用了使用getParentNode()导航树的方法。
我已经包含XPath测试来检查生成的表达式是否返回相同的节点
扩展输入以包含同一级别的不同名称的元素。
Code
public class Test {
private static String getXPath(Node root) {
Node current = root;
String output = "";
while (current.getParentNode() != null) {
Node parent = current.getParentNode();
if (parent != null && parent.getChildNodes().getLength() > 1) {
int nthChild = 1;
Node siblingSearch = current;
while ((siblingSearch = siblingSearch.getPreviousSibling()) != null) {
// only count siblings of same type
if (siblingSearch.getNodeName().equals(current.getNodeName())) {
nthChild++;
}
}
output = "/" + current.getNodeName() + "[" + nthChild + "]" + output;
} else {
output = "/" + current.getNodeName() + output;
}
current = current.getParentNode();
}
return output;
}
public static void main(String[] args) throws Exception {
String input = "<abc><def><hij /></def><def><lmn /><xyz /><lmn /></def></abc>";
Document root = DocumentBuilderFactory.newInstance()
.newDocumentBuilder()
.parse(new InputSource(new StringReader(input)));
test(root.getDocumentElement(), root);
}
private static void test(Node node, Document doc) throws Exception {
String expression = getXPath(node);
Node result = (Node) XPathFactory.newInstance().newXPath()
.compile(expression).evaluate(doc, XPathConstants.NODE);
if (result == node) {
System.out.println("Test OK : " + expression);
} else {
System.out.println("Test Fail: " + expression);
}
for (int i = 0; i < node.getChildNodes().getLength(); i++) {
test(node.getChildNodes().item(i), doc);
}
}
}
Output
Test OK : /abc
Test OK : /abc/def[1]
Test OK : /abc/def[1]/hij
Test OK : /abc/def[2]
Test OK : /abc/def[2]/lmn[1]
Test OK : /abc/def[2]/xyz[1]
Test OK : /abc/def[2]/lmn[2]
#1
0
<abc>
<def>
</hij>
</def>
<def>
</lmn>
</def>
</abc>
In here. You are closing
在这里。你正在结束
</hij>
and
</lmn>
without opening them. If you are opening them before abc, them you can't close them inside abc. Basically: You can't intertwince them. Open one, open second, close second, close one. Never in another way around.
没有打开它们。如果你在abc之前打开它们,你就无法在abc中关闭它们。基本上:你不能交织他们。打开一个,打开第二个,关闭第二个,关闭一个。从来没有以另一种方式。
This might lead to your error
这可能会导致您的错误
#2
0
I'm unable to fix your code in the question as it is not complete, for example where is map defined? Also see other answer about your malformed input.
我无法在问题中修复您的代码,因为它不完整,例如地图定义在哪里?另请参阅有关您的格式错误输入的其他答案。
Making the assumption that hij and lmn should have been short tags, here is a complete solution.
假设hij和lmn应该是短标签,这是一个完整的解决方案。
- I used the approach of navigating up the tree using getParentNode().
- I've included XPath tests to check that the generated expression returns the same node
- Extended input to contain elements of different names at the same level.
我使用了使用getParentNode()导航树的方法。
我已经包含XPath测试来检查生成的表达式是否返回相同的节点
扩展输入以包含同一级别的不同名称的元素。
Code
public class Test {
private static String getXPath(Node root) {
Node current = root;
String output = "";
while (current.getParentNode() != null) {
Node parent = current.getParentNode();
if (parent != null && parent.getChildNodes().getLength() > 1) {
int nthChild = 1;
Node siblingSearch = current;
while ((siblingSearch = siblingSearch.getPreviousSibling()) != null) {
// only count siblings of same type
if (siblingSearch.getNodeName().equals(current.getNodeName())) {
nthChild++;
}
}
output = "/" + current.getNodeName() + "[" + nthChild + "]" + output;
} else {
output = "/" + current.getNodeName() + output;
}
current = current.getParentNode();
}
return output;
}
public static void main(String[] args) throws Exception {
String input = "<abc><def><hij /></def><def><lmn /><xyz /><lmn /></def></abc>";
Document root = DocumentBuilderFactory.newInstance()
.newDocumentBuilder()
.parse(new InputSource(new StringReader(input)));
test(root.getDocumentElement(), root);
}
private static void test(Node node, Document doc) throws Exception {
String expression = getXPath(node);
Node result = (Node) XPathFactory.newInstance().newXPath()
.compile(expression).evaluate(doc, XPathConstants.NODE);
if (result == node) {
System.out.println("Test OK : " + expression);
} else {
System.out.println("Test Fail: " + expression);
}
for (int i = 0; i < node.getChildNodes().getLength(); i++) {
test(node.getChildNodes().item(i), doc);
}
}
}
Output
Test OK : /abc
Test OK : /abc/def[1]
Test OK : /abc/def[1]/hij
Test OK : /abc/def[2]
Test OK : /abc/def[2]/lmn[1]
Test OK : /abc/def[2]/xyz[1]
Test OK : /abc/def[2]/lmn[2]