javax.xml.parsers.DocumentBuilder
可以从单个流构建文档,该流是XML文件。但是,我找不到任何方法也给它一个模式文件。
有没有办法做到这一点,以便我的XPath查询可以执行类型感知查询并返回类型化数据?
答案 0 :(得分:1)
JAXP API是为XPath 1.0设计的,从未升级为处理类似于架构的查询等2.0概念。如果您使用的是Saxon,请使用s9api接口而不是JAXP。
以下是在saxon-resources下载中从s9apiExamples.java中获取的模式感知XPath的示例:
/**
* Demonstrate use of a schema-aware XPath expression
*/
private static class XPathC implements S9APIExamples.Test {
public String name() {
return "XPathC";
}
public boolean needsSaxonEE() {
return true;
}
public void run() throws SaxonApiException {
Processor proc = new Processor(true);
SchemaManager sm = proc.getSchemaManager();
sm.load(new StreamSource(new File("data/books.xsd")));
SchemaValidator sv = sm.newSchemaValidator();
sv.setLax(false);
XPathCompiler xpath = proc.newXPathCompiler();
xpath.declareNamespace("saxon", "http://saxon.sf.net/"); // not actually used, just for demonstration
xpath.importSchemaNamespace(""); // import schema for the non-namespace
DocumentBuilder builder = proc.newDocumentBuilder();
builder.setLineNumbering(true);
builder.setWhitespaceStrippingPolicy(WhitespaceStrippingPolicy.ALL);
builder.setSchemaValidator(sv);
XdmNode booksDoc = builder.build(new File("data/books.xml"));
// find all the ITEM elements, and for each one display the TITLE child
XPathSelector verify = xpath.compile(". instance of document-node(schema-element(BOOKLIST))").load();
verify.setContextItem(booksDoc);
if (((XdmAtomicValue)verify.evaluateSingle()).getBooleanValue()) {
XPathSelector selector = xpath.compile("//schema-element(ITEM)").load();
selector.setContextItem(booksDoc);
QName titleName = new QName("TITLE");
for (XdmItem item: selector) {
XdmNode title = getChild((XdmNode)item, titleName);
System.out.println(title.getNodeName() +
"(" + title.getLineNumber() + "): " +
title.getStringValue());
}
} else {
System.out.println("Verification failed");
}
}
// Helper method to get the first child of an element having a given name.
// If there is no child with the given name it returns null
private static XdmNode getChild(XdmNode parent, QName childName) {
XdmSequenceIterator iter = parent.axisIterator(Axis.CHILD, childName);
if (iter.hasNext()) {
return (XdmNode)iter.next();
} else {
return null;
}
}
}