带有Saxon的Apache Camel Xpath 2.0在RouteBuilder/谓词中看起来不起作用
我使用的是ServiceMix 4.5.3,其中包括Camel 2.10.7,并且我能够使用以下端点选项对Saxon库进行XSLT 2.0转换:带有Saxon的Apache Camel Xpath 2.0在RouteBuilder/谓词中看起来不起作用,xpath,apache-camel,saxon,xpath-2.0,Xpath,Apache Camel,Saxon,Xpath 2.0,我使用的是ServiceMix 4.5.3,其中包括Camel 2.10.7,并且我能够使用以下端点选项对Saxon库进行XSLT 2.0转换: ... to("xslt:stylesheet.xsl?transformerFactoryClass=net.sf.saxon.TransformerFactoryImpl") ... private Namespaces ourNS = new Namespaces("myns", "urn:com:company:domain:
...
to("xslt:stylesheet.xsl?transformerFactoryClass=net.sf.saxon.TransformerFactoryImpl")
...
private Namespaces ourNS = new Namespaces("myns",
"urn:com:company:domain:namespace:myns/1");
// ... some code ...
// Make a predicate to filter according a header :
// The code attribute looks like: urn:phone:apple:iphone:4s
Predicate isNotSamePhoneBrand = PredicateBuilder.isNotEqualTo(
xpath("tokenize(/myns:Phone/@code, ':')[3]").namespaces(ourNS),
header("PhoneBrand"));
.factory(new net.sf.saxon.xpath.XPathFactoryImpl())
Predicate isNotSamePhoneBrand = PredicateBuilder.isNotEqualTo(
xpath("tokenize(/myns:Phone/@code, ':')[3]").namespaces(ourNS)
.factory(new net.sf.saxon.xpath.XPathFactoryImpl()).resultType(String.class),
header("PhoneBrand"));
net.sf.saxon.xpath.XPathFactoryImpl factory = new net.sf.saxon.xpath.XPathFactoryImpl();
XPath xpath = factory.newXPath();
NodeList channels = (NodeList) xpath.evaluate(
"//*:Channels/*:Channel/text()",
body, XPathConstants.NODESET);
但是,当我尝试像这样使用xpath函数时:
...
to("xslt:stylesheet.xsl?transformerFactoryClass=net.sf.saxon.TransformerFactoryImpl")
...
private Namespaces ourNS = new Namespaces("myns",
"urn:com:company:domain:namespace:myns/1");
// ... some code ...
// Make a predicate to filter according a header :
// The code attribute looks like: urn:phone:apple:iphone:4s
Predicate isNotSamePhoneBrand = PredicateBuilder.isNotEqualTo(
xpath("tokenize(/myns:Phone/@code, ':')[3]").namespaces(ourNS),
header("PhoneBrand"));
.factory(new net.sf.saxon.xpath.XPathFactoryImpl())
Predicate isNotSamePhoneBrand = PredicateBuilder.isNotEqualTo(
xpath("tokenize(/myns:Phone/@code, ':')[3]").namespaces(ourNS)
.factory(new net.sf.saxon.xpath.XPathFactoryImpl()).resultType(String.class),
header("PhoneBrand"));
net.sf.saxon.xpath.XPathFactoryImpl factory = new net.sf.saxon.xpath.XPathFactoryImpl();
XPath xpath = factory.newXPath();
NodeList channels = (NodeList) xpath.evaluate(
"//*:Channels/*:Channel/text()",
body, XPathConstants.NODESET);
如果我执行上面的代码,它会说tokenize函数是未知的。我想这是因为它仍然使用XalanXPath1.0而不是Saxon
我还尝试在Camel文档中添加.saxon
Predicate isNotSamePhoneBrand = PredicateBuilder.isNotEqualTo(
xpath("tokenize(/myns:Phone/@code, ':')[3]").namespaces(ourNS).saxon(),
header("PhoneBrand"));
但他无法找到Saxon实现工厂,这是一个错误:
Caused by: javax.xml.xpath.XPathFactoryConfigurationException: No XPathFctory implementation found for the object model: http://saxon.sf.net/jaxp/xpath/om
在我的OSGI上下文中,我验证了camel-saxon和ApacheServiceMix::Bundles::saxon9he 9.3.0.112都已部署
我们计划很快升级到ServiceMix 5,但我不知道这个问题是否仍然存在,4.5.3版的解决方案对我来说会更好。在Saxon 9.6中,我们删除了将Saxon注册为JAXP XPathFactory接口实现的服务文件。它仍然实现该接口,只是在JAR文件清单中没有这样的服务文件。这背后有很长的历史,但基本上有两个主要原因:JDK版本之间的不兼容导致无法生成从JDK 5到JDK 8(包括JDK 5到JDK 8)的服务文件;b仅仅将Saxon放在类路径上会导致应用程序在未编写或测试以使用XPath 2.0的情况下崩溃
我想,通过将服务文件添加到SAXON Jar文件清单,您可以自己复制9.5版本中的服务文件,这是一个解决方案。最后,我找到了一个骆驼路线的有效解决方案: 由于.saxon对我的路径没有影响,我决定换一种方式看,我发现有一个特定的选项可以覆盖Xpath工厂,如下所示:
...
to("xslt:stylesheet.xsl?transformerFactoryClass=net.sf.saxon.TransformerFactoryImpl")
...
private Namespaces ourNS = new Namespaces("myns",
"urn:com:company:domain:namespace:myns/1");
// ... some code ...
// Make a predicate to filter according a header :
// The code attribute looks like: urn:phone:apple:iphone:4s
Predicate isNotSamePhoneBrand = PredicateBuilder.isNotEqualTo(
xpath("tokenize(/myns:Phone/@code, ':')[3]").namespaces(ourNS),
header("PhoneBrand"));
.factory(new net.sf.saxon.xpath.XPathFactoryImpl())
Predicate isNotSamePhoneBrand = PredicateBuilder.isNotEqualTo(
xpath("tokenize(/myns:Phone/@code, ':')[3]").namespaces(ourNS)
.factory(new net.sf.saxon.xpath.XPathFactoryImpl()).resultType(String.class),
header("PhoneBrand"));
net.sf.saxon.xpath.XPathFactoryImpl factory = new net.sf.saxon.xpath.XPathFactoryImpl();
XPath xpath = factory.newXPath();
NodeList channels = (NodeList) xpath.evaluate(
"//*:Channels/*:Channel/text()",
body, XPathConstants.NODESET);
之后,我必须强制将Xpath的结果转换为带有.resultTypeString.class的字符串
完整谓词如下所示:
...
to("xslt:stylesheet.xsl?transformerFactoryClass=net.sf.saxon.TransformerFactoryImpl")
...
private Namespaces ourNS = new Namespaces("myns",
"urn:com:company:domain:namespace:myns/1");
// ... some code ...
// Make a predicate to filter according a header :
// The code attribute looks like: urn:phone:apple:iphone:4s
Predicate isNotSamePhoneBrand = PredicateBuilder.isNotEqualTo(
xpath("tokenize(/myns:Phone/@code, ':')[3]").namespaces(ourNS),
header("PhoneBrand"));
.factory(new net.sf.saxon.xpath.XPathFactoryImpl())
Predicate isNotSamePhoneBrand = PredicateBuilder.isNotEqualTo(
xpath("tokenize(/myns:Phone/@code, ':')[3]").namespaces(ourNS)
.factory(new net.sf.saxon.xpath.XPathFactoryImpl()).resultType(String.class),
header("PhoneBrand"));
net.sf.saxon.xpath.XPathFactoryImpl factory = new net.sf.saxon.xpath.XPathFactoryImpl();
XPath xpath = factory.newXPath();
NodeList channels = (NodeList) xpath.evaluate(
"//*:Channels/*:Channel/text()",
body, XPathConstants.NODESET);
现在,标记化函数xpath 2.0已经得到了很好的认可
我发现在骆驼处理器中使用工厂实现时,我必须对工厂实现的实例化做同样的事情,如下所示:
...
to("xslt:stylesheet.xsl?transformerFactoryClass=net.sf.saxon.TransformerFactoryImpl")
...
private Namespaces ourNS = new Namespaces("myns",
"urn:com:company:domain:namespace:myns/1");
// ... some code ...
// Make a predicate to filter according a header :
// The code attribute looks like: urn:phone:apple:iphone:4s
Predicate isNotSamePhoneBrand = PredicateBuilder.isNotEqualTo(
xpath("tokenize(/myns:Phone/@code, ':')[3]").namespaces(ourNS),
header("PhoneBrand"));
.factory(new net.sf.saxon.xpath.XPathFactoryImpl())
Predicate isNotSamePhoneBrand = PredicateBuilder.isNotEqualTo(
xpath("tokenize(/myns:Phone/@code, ':')[3]").namespaces(ourNS)
.factory(new net.sf.saxon.xpath.XPathFactoryImpl()).resultType(String.class),
header("PhoneBrand"));
net.sf.saxon.xpath.XPathFactoryImpl factory = new net.sf.saxon.xpath.XPathFactoryImpl();
XPath xpath = factory.newXPath();
NodeList channels = (NodeList) xpath.evaluate(
"//*:Channels/*:Channel/text()",
body, XPathConstants.NODESET);
这不是动态的,但我想在任何地方强制使用Saxon,这样这个解决方案就符合我们的需要。Ok,那么它看起来更像是JVM的类路径问题,而不是ServiceMix中的特定问题。这就解释了为什么有时候它可以在JUnitEclipseJVM中工作,而不能在集成测试SMXJVM中工作。我会找到一个解决方案,但还不确定它是否有效。啊,请注意你所说的版本。但我认为我们有在SMX控制台中编写的9.3.0.112。正如您所说,我们应该能够使用9.6之前的服务。但它似乎不能按原样工作。您使用的JDK版本是什么?众所周知,我们以前包含的服务文件与JDK 8不兼容。我们在centos 6.5下使用JDK 7 me,在windows 7下使用我的同事。。。但两个平台上的效果相同谢谢你的帖子,它帮助我找到合适的解决方案,看看我的答案