我們如何獲得FreeMarker中節點的XPath。我想知道synatax。 就像我正在處理一個節點並希望以XML獲取其地址一樣。FreeMarker XML Xpath
類似於:node?node_xpath。
我們如何獲得FreeMarker中節點的XPath。我想知道synatax。 就像我正在處理一個節點並希望以XML獲取其地址一樣。FreeMarker XML Xpath
類似於:node?node_xpath。
沒有這樣的東西存在開箱即用。你可以爲它編寫一個自定義方法(TemplateMethodModelEx
實現)。無論如何你需要什麼樣的路徑?像/node()[0]/node()[3]/node()[2]
?我相信W3C DOM API沒有方法來查詢節點的索引,因此您必須掃描節點父節點的子節點以查找其索引。 (這是一個DOM限制,而不是FreeMarker的限制。)或者如果你對這個模式有更多的瞭解,你可能需要像/foo/bar[@id=123]/baaz
這樣的東西,但這顯然不是一個通用的功能。
試試這個:
public class GetXPathFromNode implements TemplateMethodModelEx {
public Object exec(List args) throws TemplateModelException {
if(args.size() != 1){
throw new TemplateModelException("Please specify one xml node.");
}
NodeModel node = (NodeModel) args.get(0);
return getXPath(node.getNode());
}
private String getXPath(Node node) {
StringBuilder sb = new StringBuilder("/");
String attribute = "";
if(node.getNodeType() == Node.ATTRIBUTE_NODE){
attribute = "/@" + node.getNodeName();
Attr attr = (Attr) node;
node = attr.getOwnerElement();
}
sb.append(node.getNodeName())
.append("[").append(getNodeIndex(node)).append("]").append(attribute);
return renderNodeXpath(node, sb).toString();
}
private StringBuilder renderNodeXpath(Node node, StringBuilder path){
Node parentNode = node.getParentNode();
if(parentNode != null && parentNode.getNodeType() != Node.DOCUMENT_NODE){
StringBuilder sb2 = new StringBuilder("/");
sb2.append("[").append(getNodeIndex(parentNode)).append("]");
path.insert(0,sb2);
return renderNodeXpath(parentNode, path);
}
return path;
}
private int getNodeIndex(Node childNode) {
Node parentNode = childNode.getParentNode();
if(parentNode == null){
return 1;
}
int index = 1;
for(int i = 0; parentNode.getChildNodes().getLength() >= i; i++){
Node node = parentNode.getChildNodes().item(i);
if(node.isSameNode(childNode)){
return index; // this is used to ignore empty text nodes.
}
if(node.getNodeType() != Node.TEXT_NODE){
index++;
}
}
return 1;
}
}