问题是我正在寻找一个XPath表达式,以获取具有属性XXX的节点,这些属性的值像TP *一样,其中星号是数字。 假设我有这个XML文件
<tagA attA="VAL1">text</tagA>
<tagB attB="VAL333">text</tagB>
<tagA attA="VAL2">text</tagA>
<tagA attA="V2">text</tagA>
因此,xpath表达式应该使我所有拥有属性tagA
的{{1}}都具有模式attrA
的值
VAL*
:不起作用
请帮忙吗?
答案 0 :(得分:4)
如果您需要XPath 1.0解决方案,请尝试以下操作:
//tagA[boolean(number(substring-after(@attA, "VAL"))) or number(substring-after(@attA, "VAL")) = 0]
如果@attA
不能为"VAL0"
,那么
//tagA[boolean(number(substring-after(@attA, "VAL")))]
答案 1 :(得分:2)
matches()
需要 XPath 2.0 ,但是Java 8中的javax.xml.xpath仅支持XPath 1.0。
此外,matches()
的第一个参数是要匹配的字符串。所以,您想要:
//tagA[@attrA[matches(., 'VAL\d')]]
这是在"VAL"
的属性值中的任意位置寻找@attrA
和一位数字。如果您希望将整个字符串与多个/可选的数字后缀(XPath 2.0)或@jschnasse's answer匹配以获取XPath 1.0解决方案,请参见Andersson's answer中的正则表达式。
答案 2 :(得分:1)
向您的*
添加一个量词(+
,\d
,...)。试试
'^VAL\d*$'
正如@ kjhughes所指出的。这不适用于标准Java,因为即使Java 11的当前版本也不支持XPath 2.0。 但是,如果需要XPath 2.0支持,则可以使用Saxon。
撒克逊人的例子(它是variant of this answer using javax.xml)
Processor processor = new Processor(false);
@Test
public void xpathWithSaxon() {
String xml = "<root><tagA attA=\"VAL1\">text</tagA>\n" + "<tagB attB=\"VAL333\">text</tagB>\n"
+ "<tagA attA=\"VAL2\">text</tagA>\n" + "<tagA attA=\"V2\">text</tagA>\n" + "</root>";
try (InputStream in = new ByteArrayInputStream(xml.getBytes("utf-8"));) {
processFilteredXmlWith(in, "//root/tagA[matches(@attA,'^VAL\\d*$')]", (node) -> {
printItem(node, System.out);
});
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void printItem(XdmItem node, PrintStream out) {
out.println(node);
}
public void processFilteredXmlWith(InputStream in, String xpath, Consumer<XdmItem> process) {
XdmNode doc = readXmlWith(in);
XdmValue list = filterNodesByXPathWith(doc, xpath);
list.forEach((node) -> {
process.accept(node);
});
}
private XdmNode readXmlWith(InputStream xmlin) {
try {
return processor.newDocumentBuilder().build(new StreamSource(xmlin));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private XdmValue filterNodesByXPathWith(XdmNode doc, String xpathExpr) {
try {
return processor.newXPathCompiler().evaluate(xpathExpr, doc);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
打印
<tagA attA="VAL1">text</tagA>
<tagA attA="VAL2">text</tagA>