【发布时间】:2015-08-24 18:18:24
【问题描述】:
我想获取包含重复元素的 XML 文档的 XPath。
示例:
<Return>
<ReturnData>
<Person>
<Name>Yohanna</Name>
</Person>
<Person>
<Name>Jacoub</Name>
</Person>
</ReturnData>
</Return>
我想退货:
1. /Return/ReturnData/Person[1]/Name=Yohanna
2. /Return/ReturnData/Person[2]/Name=Jacoub
我有一个实现,它可以为我检索任何 XML 文档的 XPath,但是我有重复 XPath 的问题,我不确定如何索引 XPath 是唯一的,因此我可以将值分配给它作为 Key/Value 对正如我在上面展示的那样。我想我应该使用 Map 数据结构,但我不确定如何做到这一点。
这是我的代码:
public List<String> getXPaths ( InputStream stream ) throws ParserException {
Document document = XMLUtils.getDocument( stream );
return getXPaths( document.getDocumentElement() );
}
public List<String> getXPaths ( Node node ) {
List<String> xpaths = iterate( node, "");
return xpaths;
}
public List<String> iterate ( Node node, String parentPath ) {
List<String> xpaths = new ArrayList<String>();
if ( node.getNodeType() == Node.ELEMENT_NODE ) {
Element element = ( Element ) node;
parentPath = parentPath + "/" + element.getTagName();
for ( int nIndex = 0; nIndex<node.getChildNodes().getLength(); nIndex++ ) {
xpaths.addAll( iterate(node.getChildNodes().item(nIndex) , parentPath ) ) ;
}
}
else if ( node.getNodeType() == Node.TEXT_NODE ) {
if ( node.getTextContent().trim().length() !=0 ) {
logger.debug("XPath found : " + parentPath );
xpaths.add( parentPath );
}
}
else {
logger.debug("Unknown node type for : " + node.getNodeName());
}
return xpaths;
}
目前,此代码仅返回一个未编入索引的 XPath 列表:
输出:
/Return/ReturnData/Person/Name
/Return/ReturnData/Person/Name
我们将不胜感激。
另一个修改:
public String getFullXPathV2(Node n) {
...etc.
while (null != prev_sibling) {
if (prev_sibling.getNodeType() == node.getNodeType()) {
if (prev_sibling.getNodeName().equalsIgnoreCase(node.getNodeName())) {
prev_siblings++;
}
}
prev_sibling = prev_sibling.getPreviousSibling();
}
// Edit here
if(prev_siblings == 1) {
continue;
}
else
builder.append("[").append(prev_siblings).append("]");
}
else if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
builder.append("/@");
builder.append(node.getNodeName());
}
}
return builder.toString();
}
输出:
[/Return/ReturnData/Person/Name = Yohanna, /Return/ReturnData/Person[2]/Name = Jacoub]
这似乎没问题,但是 /Return/ReturnData/Person/Name = Yohanna 它应该是 /Person[1] 来表示它第一次出现 Person 节点。
【问题讨论】: