如何使用Saxon S9API在org.w3c.dom.Document上执行XPath 2.0表达式?
解决Saxon XPathSelector在org.w3c.dom.Document上执行查询的问题
你遇到的核心问题是没有将原生的org.w3c.dom.Document转换为Saxon能识别的XdmNode对象,也没有为XPathSelector设置查询的上下文节点。Saxon的XPath API依赖自身的XDM(XPath Data Model)对象模型,直接调用evaluate()而不指定上下文文档自然会抛出异常。
下面是修正后的完整代码,我会标注关键修改点:
import net.sf.saxon.s9api.*; import org.w3c.dom.Document; import org.xml.sax.InputSource; import com.sun.org.apache.xerces.internal.parsers.DOMParser; import javax.xml.transform.dom.DOMSource; import java.io.FileInputStream; import java.util.ArrayList; public class XPath2Test { public static void main(String[] args) throws Exception{ String assemblyXPathString="/child::AssemblyBase/child::Assembly[attribute::roles='ALL' or contains(attribute::roles,$role)]"; // 原有的DOM解析部分 DOMParser parser=new DOMParser(); FileInputStream fis=new FileInputStream("E:\\workspaces\\dev_werewolf\\Platform_Manual\\manual\\UIFramework\\RoleBasedUIAssembly2.xml"); InputSource inputSource=new InputSource(fis); parser.parse(inputSource); Document document=parser.getDocument(); // Saxon初始化部分 Processor processor=new Processor(false); XPathCompiler compiler=processor.newXPathCompiler(); compiler.declareVariable(new QName("role")); XPathExecutable executable=compiler.compile(assemblyXPathString); XPathSelector selector=executable.load(); // 设置变量 ArrayList<String> values=new ArrayList<>(); values.add("CIO"); selector.setVariable(new QName("role"), XdmItem.makeSequence(values)); // ------------------- 关键修改部分 ------------------- // 1. 将org.w3c.dom.Document转换为Saxon的XdmNode DOMSource domSource = new DOMSource(document); XdmNode xdmNode = processor.newDocumentBuilder().build(domSource); // 2. 将XdmNode设置为XPathSelector的上下文节点 selector.setContextItem(xdmNode); // --------------------------------------------------- // 执行查询并处理结果 XdmValue result = selector.evaluate(); // 遍历结果示例 for (XdmItem item : result) { System.out.println(item.getStringValue()); } } }
关键知识点说明:
- DOM到XDM的转换:Saxon提供了
DocumentBuilder.build(DOMSource)方法,可以把原生DOM对象转换成Saxon的XdmNode,这是让Saxon能识别并处理你现有DOM文档的核心步骤。 - 设置上下文节点:
XPathSelector.setContextItem()方法指定了XPath查询的根节点(也就是你的整个文档),没有这个步骤,Selector不知道要在哪个文档上执行查询。 - 结果处理:
evaluate()方法返回XdmValue,你可以遍历这个对象来获取匹配到的所有节点或值。
另外,注意如果你的项目中使用的是较新版本的Saxon(比如10+),可能需要调整导入的包路径,但核心逻辑是一致的。
内容的提问来源于stack exchange,提问作者Ironluca
相关产品推荐
相关产品推荐

