gpt4 book ai didi

java - 如何使用 saxon 将外部输入绑定(bind)到 xquery?

转载 作者:行者123 更新时间:2023-11-30 08:12:04 27 4
gpt4 key购买 nike

我必须使用 saxon HE 在 xquery 中调用外部 java 方法。我可以使用下面的代码调用这些方法。但问题是我想在外部绑定(bind)我的输入。

final Configuration config = new Configuration();
config.registerExtensionFunction(new ShiftLeft());
final StaticQueryContext sqc = new StaticQueryContext(config);
final XQueryExpression exp = sqc.compileQuery(new FileReader(
"input/names.xq"));

final DynamicQueryContext dynamicContext = new DynamicQueryContext(config);

String xml = "<student_list><student><name>George Washington</name><major>Politics</major><phone>312-123-4567</phone><email>gw@example.edu</email></student><student><name>Janet Jones</name><major>Undeclared</major><phone>311-122-2233</phone><email>janetj@example.edu</email></student><student><name>Joe Taylor</name><major>Engineering</major><phone>211-111-2333</phone><email>joe@example.edu</email></student></student_list>";
DocumentBuilderFactory newInstance = DocumentBuilderFactory.newInstance();
newInstance.setNamespaceAware(true);
Document parse = newInstance.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
DocumentWrapper sequence = new DocumentWrapper(parse, "", config);
StructuredQName qname = new StructuredQName("", "", "student_list");
dynamicContext.setParameter(qname, sequence);

Properties props = new Properties();
final SequenceIterator iter = exp.iterator(dynamicContext);
props.setProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
props.setProperty(OutputKeys.INDENT, "yes");

StringWriter writer = new StringWriter();
QueryResult.serializeSequence(iter, config, writer, props);
System.out.println("Result is " + writer);

名称.xq

declare namespace eg="http://example.com/saxon-extension";
declare namespace xs = "http://www.w3.org/2001/XMLSchema";
declare variable $student_list as element(*) external;

<Students>
<value> {
let $n := eg:shift-left(2, 2)
return $n
}</value>
<student_names>
{ $student_list//student_list/student/name }
</student_names>
</Students>

但出现以下错误

Error at procedure student_list on line 3 of students.xml:
XPTY0004: Required item type of value of variable $student_list is element(); supplied
value has item type document-node(element(Q{}student_list))
net.sf.saxon.trans.XPathException: Required item type of value of variable $student_list is element(); supplied value has item type document- node(element(Q{}student_list))
at net.sf.saxon.expr.ItemTypeCheckingFunction.testConformance(ItemTypeCheckingFunction.java:69)
at net.sf.saxon.expr.ItemTypeCheckingFunction.mapItem(ItemTypeCheckingFunction.java:50)
at net.sf.saxon.expr.ItemMappingIterator.next(ItemMappingIterator.java:95)
at net.sf.saxon.expr.CardinalityCheckingIterator.<init>(CardinalityCheckingIterator.java:52)
at net.sf.saxon.type.TypeHierarchy.applyFunctionConversionRules(TypeHierarchy.java:230)
at net.sf.saxon.expr.instruct.GlobalParameterSet.convertParameterValue(GlobalParameterSet.java:105)
at net.sf.saxon.expr.instruct.Bindery.useGlobalParameter(Bindery.java:136)
at net.sf.saxon.expr.instruct.GlobalParam.evaluateVariable(GlobalParam.java:62)
at net.sf.saxon.expr.GlobalVariableReference.evaluateVariable(GlobalVariableReference.java:105)
at net.sf.saxon.expr.VariableReference.evaluateItem(VariableReference.java:460)
at net.sf.saxon.expr.Atomizer.evaluateItem(Atomizer.java:313)
at net.sf.saxon.expr.Atomizer.evaluateItem(Atomizer.java:35)
at net.sf.saxon.expr.AtomicSequenceConverter.evaluateItem(AtomicSequenceConverter.java:275)
at net.sf.saxon.expr.AtomicSequenceConverter.evaluateItem(AtomicSequenceConverter.java:30)
at net.sf.saxon.functions.Doc.doc(Doc.java:235)
at net.sf.saxon.functions.Doc.evaluateItem(Doc.java:190)
at net.sf.saxon.functions.Doc.evaluateItem(Doc.java:28)
at net.sf.saxon.expr.SimpleStepExpression.iterate(SimpleStepExpression.java:85)
at net.sf.saxon.expr.SlashExpression.iterate(SlashExpression.java:842)
at net.sf.saxon.expr.sort.DocumentSorter.iterate(DocumentSorter.java:168)
at net.sf.saxon.expr.SlashExpression.iterate(SlashExpression.java:842)
at net.sf.saxon.expr.sort.DocumentSorter.iterate(DocumentSorter.java:168)
at net.sf.saxon.expr.Expression.process(Expression.java:552)
at net.sf.saxon.expr.instruct.ElementCreator.processLeavingTail(ElementCreator.java:450)
at net.sf.saxon.expr.instruct.ElementCreator.processLeavingTail(ElementCreator.java:389)
at net.sf.saxon.expr.instruct.Block.processLeavingTail(Block.java:669)
at net.sf.saxon.expr.instruct.Instruction.process(Instruction.java:144)
at net.sf.saxon.expr.instruct.ElementCreator.constructElement(ElementCreator.java:539)
at net.sf.saxon.expr.instruct.ElementCreator.evaluateItem(ElementCreator.java:476)
at net.sf.saxon.expr.instruct.Instruction.iterate(Instruction.java:363)
at net.sf.saxon.query.XQueryExpression.iterator(XQueryExpression.java:332)
at com.example.saxon.ExternalMethodCaller.main(ExternalMethodCaller.java:77)

提前致谢..

最佳答案

除非您有充分的理由不这样做,否则我的建议是使用 Snappi(Saxon 9 API,或 s9api):

Processor saxon = new Processor(false);
saxon.registerExtensionFunction(new MyExtension());

XQueryCompiler compiler = saxon.newXQueryCompiler();
XQueryExecutable exec = compiler.compile(new File("input/names.xq"));
XQueryEvaluator query = exec.load();

DocumentBuilder builder = saxon.newDocumentBuilder();
String students = "<xml>...</xml>";
Source src = new StreamSource(new StringReader(students));
XdmNode doc = builder.build(src);
query.setExternalVariable(new QName("student_list"), doc);

XdmValue result = query.evaluate();

MyExtension 看起来如下所示:

public class MyExtension
implements ExtensionFunction
{
@Override
public QName getName()
{
return new QName("http://example.org/my-project", "my-fun");
}

@Override
public SequenceType getResultType()
{
return SequenceType.makeSequenceType(
ItemType.INTEGER, OccurrenceIndicator.ONE);
}

@Override
public SequenceType[] getArgumentTypes()
{
return new SequenceType[] {
SequenceType.makeSequenceType(
ItemType.INTEGER, OccurrenceIndicator.ONE),
SequenceType.makeSequenceType(
ItemType.INTEGER, OccurrenceIndicator.ONE)
};
}

@Override
public XdmValue call(XdmValue[] args) throws SaxonApiException
{
long first = ((XdmAtomicValue)args[0].itemAt(0)).getLongValue();
long second = ((XdmAtomicValue)args[0].itemAt(0)).getLongValue();
long result = ...;
return new XdmAtomicValue(result);
}
}

请参阅 http://www.saxonica.com/documentation9.5/extensibility/integratedfunctions/ext-simple-J.html 处的文档了解详情。

EXPath 还有一个名为 tools-saxon 的项目,其中包含几个在 Java 中使用 Saxon 的工具。包括扩展功能。它引入了函数库的概念,如果您有多个扩展函数,这会很方便。它还引入了一个函数定义构建器,允许人们用尽可能少的样板代码构建函数定义(并为类型序列提供方便的快捷方式)。在上面的代码中,将注册函数(前两行)替换为:

Processor saxon = new Processor(false);
Library lib = new MyLibrary();
lib.register(saxon.getUnderlyingConfiguration());

并将扩展类替换为以下 2 个类(分别是一个库和一个函数):

public class MyLibrary
extends Library
{
public MyLibrary()
{
super("http://example.org/my-project", "my");
}

@Override
protected Function[] functions()
{
return new Function[] {
new MyFunction(this)
};
}

}

public class MyFunction
extends Function
{
public MyFunction(Library lib)
{
super(lib);
}

@Override
protected Definition makeDefinition()
{
return library()
.function(this, "my-fun")
.returns(Types.SINGLE_INTEGER)
.param(Types.SINGLE_INTEGER, "first")
.param(Types.SINGLE_INTEGER, "second")
.make();
}

@Override
public Sequence call(XPathContext ctxt, Sequence[] args)
throws XPathException
{
Parameters params = checkParams(args);
long first = params.asLong(0, true);
long second = params.asLong(1, true);
long result = 0;
return Return.value(result);
}
}

查看 Github 上项目主页的所有信息,地址:https://github.com/expath/tools-saxon .

注意:未经测试。

关于java - 如何使用 saxon 将外部输入绑定(bind)到 xquery?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30255908/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com