Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带有Saxon的Apache Camel Xpath 2.0在RouteBuilder/谓词中看起来不起作用_Xpath_Apache Camel_Saxon_Xpath 2.0 - Fatal编程技术网

带有Saxon的Apache Camel Xpath 2.0在RouteBuilder/谓词中看起来不起作用

带有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:

我使用的是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: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下使用我的同事。。。但两个平台上的效果相同谢谢你的帖子,它帮助我找到合适的解决方案,看看我的答案