使用 XQuery 记录

Logging with XQuery

我正在使用 XQuery 3.0 转换传入消息以适合我的系统。 通过 transform EIP 从 Apache Camel 路由调用 XQuery。

示例:
transform().xquery("resource:classpath:xquery/myxquery.xquery",String.class)

虽然转换工作没有问题,但能够在转换过程中直接记录一些信息会很好,因为它部分非常复杂。

所以我想问一下是否可以直接从XQuery登录"into" logback ?

我已经搜索了 Whosebug,当然还有 https://www.w3.org/TR/xquery-30-use-cases/ 和其他资源,但我找不到任何关于 如何在 Xquery 中记录 的信息。

我的项目结构是:

Update:为了在 Apache-Camel 框架中集成 XQuery 我使用org.apache.camel:camel-saxon-starter:2.22.2.

更新:因为fn:trace的使用有点难看我进一步搜索,现在我使用撒克逊的扩展机制来提供不同的日志记录功能,可以是通过 xquery 访问:

有关详细信息,请参阅文档:http://www.saxonica.com/documentation/#!extensibility/integratedfunctions/ext-full-J

这是我为日志记录所做的(使用 Saxon-HE 测试,Camel 不是强制性的,我只是巧合地使用它):

第一步:

延长 class net.sf.saxon.lib.ExtensionFunctionDefinition

public class XQueryInfoLogFunctionDefinition extends ExtensionFunctionDefinition{

    private static final Logger log = LoggerFactory.getLogger(XQueryInfoLogFunctionDefinition.class);

    private final XQueryInfoExtensionFunctionCall functionCall = new XQueryInfoExtensionFunctionCall();

    private static final String PREFIX = "log";

    @Override
    public StructuredQName getFunctionQName() {
        return new StructuredQName(PREFIX, "http://thehandofnod.com/saxon-extension", "info");
    }

    @Override
    public SequenceType[] getArgumentTypes() {
        return new SequenceType[] { SequenceType.SINGLE_STRING };
    }

    @Override
    public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) {
        return SequenceType.VOID;
    }

    @Override
    public ExtensionFunctionCall makeCallExpression() {
        return functionCall;
    }

}

第二步:

实现函数调用class

public class XQueryInfoExtensionFunctionCall extends ExtensionFunctionCall {

    private static final Logger log = LoggerFactory.getLogger(XQueryInfoLogFunctionDefinition.class);

    @Override
    public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException {
        if (arguments != null && arguments.length > 0) {
            log.info(((StringValue) arguments[0]).getStringValue());
        } else
            throw new IllegalArgumentException("We need a message");
        return EmptySequence.getInstance();
    }
}

第三步:

配置 SaxonConfiguration 并将其绑定到 camel 上下文中:

    public static void main(String... args) throws Exception {
        Main main = new Main();

        Configuration saxonConfig = Configuration.newConfiguration(); 
        saxonConfig.registerExtensionFunction(new XQueryInfoLogFunctionDefinition());

        main.bind("saxonConfig", saxonConfig);
        main.addRouteBuilder(new MyRouteBuilder());
        main.run(args);
    }

第四步:

在您的 XQueryEndpoint 中定义 SaxonConfig: .to("xquery:test.xquery?configuration=#saxonConfig");

第五步:

在你的 xquery 中调用它:

declare namespace log="http://thehandofnod.com/saxon-extension";
log:info("Das ist ein INFO test")

原posta.k.a如何覆盖fn:trace功能:

感谢 Martin Honnen 我尝试了 fn:trace 功能。问题是默认情况下它登录到 System.err Printstream 而这不是我想要的,因为我想将 fn:trace 函数与 Logback 日志框架结合起来.

所以我调试了 net.sf.saxon.functions.Trace 方法并为我的项目设置找到了以下解决方案。

  1. 编写一个自定义的 TraceListener,它从 net.sf.saxon.trace.XQueryTraceListener 扩展,并以 InstructionInfo 和 [=28] 的方式实现方法 enterleave =](对于 user-trace)被转发到 SLF4J-API。示例(仅记录消息):
@Override
    public void enter(InstructionInfo info, XPathContext context) {
        // no call to super to keep it simple.
        String nachricht = (String) info.getProperty("label");
        if (info.getConstructType() == 2041 && StringUtils.hasText(nachricht)) {
            getLogger().info(nachricht);
        }
    }

    @Override
    public void leave(InstructionInfo info) {
        // no call to super to keep it simple.
    }
  1. 通过 setTraceListener

  2. 将自定义跟踪侦听器设置到您的 net.sf.saxon.Configuration Bean 中
  3. 通过 XQueryEndpoint 从 camel 调用您的 xquery 文件,因为只有在那里才有可能用选项覆盖 Configuration.to("xquery:/xquery/myxquery.xquery?configuration=#saxonConf")。不幸的是,transform().xquery(...) 使用它自己的对象而无法配置它们。

  4. 在您的 xquery 中调用 {fn:trace($element/text(),"Das ist ein Tracing Test")} 并在您的日志中查看消息。