使用 JDOM 进行标记帮助我找到了这一点。
长答案来了.... XPath 不具备解析将“属性”添加到 ProcessingInstructions 的“标准”方式的本机能力。如果您想将值串联作为单个 XPath 表达式的一部分,我认为您不走运....实际上,Martin 的答案看起来很有希望,但它会返回许多字符串值,而不是 ProcessingInsructions。JDOM 2.x 将需要 XPath.compile(...) 上的 Filters.string() 并且您将获得List<String>
path.evaluate(doc)...的结果。我认为在 XPath 之外执行此操作更简单. 特别是考虑到通过使用带有 JDOM 2.x 的 Saxon 库对 XPath2.0 的支持有限
至于以编程方式进行,JDOM 2.x 提供了相当多的帮助。以您的示例 XML 为例,我采用两种方法,第一种方法在 XPath 结果集上使用自定义过滤器。第二种方法有效地做同样的事情,但将 PI 限制在循环中。
public static void main(String[] args) throws Exception {
SAXBuilder saxb = new SAXBuilder();
Document doc = saxb.build(new File("data.xml"));
// This custom filter will return PI's that have the NAME="CONTENTTYPE" 'pseudo' attribute...
@SuppressWarnings("serial")
Filter<ProcessingInstruction> contenttypefilter = new AbstractFilter<ProcessingInstruction>() {
@Override
public ProcessingInstruction filter(Object obj) {
// because we know the XPath expression selects Processing Instructions
// we can safely cast here:
ProcessingInstruction pi = (ProcessingInstruction)obj;
if ("CONTENTTYPE".equals(pi.getPseudoAttributeValue("NAME"))) {
return pi;
}
return null;
}
};
XPathExpression<ProcessingInstruction> xp = XPathFactory.instance().compile(
// search for all METADATA PI's.
"//processing-instruction('METADATA')",
// The XPath will return ProcessingInstruction content, which we
// refine with our custom filter.
contenttypefilter);
StringBuilder sb = new StringBuilder();
for (ProcessingInstruction pi : xp.evaluate(doc)) {
sb.append(pi.getPseudoAttributeValue("VALUE")).append("\n");
}
System.out.println(sb);
}
第二种方法使用更简单的预定义方法,Filters.processingInstruction()
但随后手动进行额外的过滤......
public static void main(String[] args) throws Exception {
SAXBuilder saxb = new SAXBuilder();
Document doc = saxb.build(new File("data.xml"));
XPathExpression<ProcessingInstruction> xp = XPathFactory.instance().compile(
// search for all METADATA PI's.
"//processing-instruction('METADATA')",
// Use the pre-defined filter to set the generic type
Filters.processinginstruction());
StringBuilder sb = new StringBuilder();
for (ProcessingInstruction pi : xp.evaluate(doc)) {
if (!"CONTENTTYPE".equals(pi.getPseudoAttributeValue("NAME"))) {
continue;
}
sb.append(pi.getPseudoAttributeValue("VALUE")).append("\n");
}
System.out.println(sb);
}